home *** CD-ROM | disk | FTP | other *** search
/ Network PC / Network PC.iso / amiga utilities / disk utilities / backup / backup_restore / backup_src_v3.20.lha / FileSelect.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-12-06  |  88.8 KB  |  3,897 lines

  1. // FileSelect.c
  2. // 06 Dec 1996 11:24:53
  3.  
  4. #ifndef    BACKUP_INCLUDE
  5. #include "IncludeAll.c"
  6. #endif
  7. #include "Backup.h"
  8. #include "FileSelect.h"
  9. #include "Backup_proto.h"
  10. #include "BackupStrings.h"
  11.  
  12. #define    d(x)        ;
  13. #define    d2(x)        x;
  14.  
  15. #define    DOSLIST_FLAGS    (LDF_VOLUMES|LDF_ASSIGNS|LDF_DEVICES|LDF_READ)
  16.  
  17.  
  18. #define    EXALL_BUFFSIZE    65536l        // Buffergröße für ExAll()
  19.  
  20.  
  21. // Abmessungen des FS-Window
  22. #define    DFLT_LEFT    34
  23. #define    DFLT_TOP    31
  24. #define    DFLT_WIDTH    (442-13)
  25. #define    DFLT_HEIGHT    336
  26.  
  27. #define    MAX_FSWIDTH    531
  28. #define    MIN_FSHEIGHT    200
  29. #define    MAX_FSHEIGHT    (~0)
  30.  
  31.  
  32. #define    FSDIR_STEP    5
  33.  
  34. #define    DEFAULTLISTSIZE    512        // default-Größe der File-Liste
  35.  
  36.  
  37. struct FSNewEntry
  38.     {
  39.     struct Node fsn_Node;
  40.     struct ALVRecordInsert fsn_Insert;
  41.     };
  42.  
  43.  
  44. static UWORD ComputeX( UWORD value );
  45. static UWORD ComputeY( UWORD value );
  46. static short inROM(APTR addr);
  47. static void FSRender( void );
  48. static void InitFS(void);
  49. static BOOL BeginFileSelect(struct BackupOptions *Opts, int *FSResult);
  50. static void EndFileSelect(void);
  51. static int HandleFSMsg(void);
  52. static int FS_IDCMPHandler(struct IntuiMessage *msg, short *abortFSRead);
  53. static void __interrupt HandleFSGadgetCallback(struct Hook *hook, struct Gadget *Gad, ULONG *Code);
  54. static void HandleFSGadgetHelp(const struct Gadget *gad, USHORT code);
  55. static short HandleFSGadget(struct Gadget *gad, USHORT code, short *abortFSRead);
  56. static void ScrollFSWindow(USHORT Code, USHORT Qualifier);
  57. static BOOL HandleStrGadCode(USHORT code);
  58. static char *NormalizeName(const char *Name);
  59. static struct FSDir *GetFSDir(const char *DirName, struct FSDirEntry *Parent);
  60. static struct FSDir *ReadFSDir(const char *DirName, struct FSDir *Dir, struct FSDirEntry *Parent);
  61. static void InsertEntryList(struct List *EntryList, BOOL ClearOnly);
  62. static short BeginDir(const char *DirName, struct NextFileInfo *nfInfo);
  63. static void EndDir(struct NextFileInfo *nfInfo);
  64. static struct FSDirEntry *NextFSDirEntry(struct NextFileInfo *nfInfo);
  65. static enum FType GetFibType(long EntryType, const STRPTR Name, BPTR DirLock);
  66. static struct FSDirEntry *NewFSEntry(const char *Name, enum FType Typ);
  67. static void DestroyFSEntry(struct FSDirEntry **FSe);
  68. static struct FSDir *MakeFSDir(const char *DirName, struct BackupOptions *Options);
  69. static void RemoveFSDir(struct FSDir *Dir);
  70. static void ExtendFSDir(struct FSDir *dir);
  71. static void SetFSDirListSize(struct FSDir *dir, unsigned long NewSize);
  72. static void FindAndRedisplayDirEntry(struct FSDir *Dir, struct FSDirEntry *FSe,
  73.     ULONG FirstColumn, ULONG LastColumn, enum RedisplayMode Changed);
  74. static void DisplayFSList(struct FSDir *Dir);
  75. static void SortFSList(struct FSDir *dir);
  76. static short DifferentType(const struct FSDirEntry *fs1, const struct FSDirEntry *fs2);
  77. static void FSSubDir(struct FSDirEntry *SubDirEntry);
  78. static void FSParentDir(void);
  79. static struct FSDir *GetVolumes(void);
  80. static void DuplicateOldEntry(struct FSDir *Dir, struct FSDir *OldDir,
  81.         struct FSDirEntry *FSe);
  82. static void ReSortEntryList(struct FSDir *Dir);
  83. static char *GetFullPathName(BPTR FileLock);
  84. static struct FSDirEntry *FindFSEntry(const char *Name, struct FSDir *Dir);
  85. static void SelectDirEntry(struct FSDir *Dir, short n, BOOL Manual);
  86. static void DeselectDirEntry(struct FSDir *Dir, short n, BOOL Manual);
  87. static void SelectChildEntry(struct FSDir *Dir, struct FSDirEntry *FSe, short Level);
  88. static void InternalSelectEntry(struct FSDir *Dir, struct FSDirEntry *FSe,
  89.     BOOL Select, BOOL Manual, short Level, BOOL Recursive);
  90. static char *FindParentName(char *DirName);
  91. static void SelectFSAttr(BOOL Select);
  92. static BOOL LookUpFSDir(char *ParentName, char *DirName);
  93. static struct FSDir *LookUpSubDir(char *ParentName, unsigned long *n);
  94. static struct FSDir *LookUpParentDir(const char *SubDirName, unsigned long *n);
  95. static void EmptyFSDir(struct FSDir *dir);
  96. static short SetFSHasSelects(struct FSDir *Dir);
  97. static BOOL isleap(short year);
  98. static void SetupBackupOpts(struct BackupOptions *NewOpts, const char *CmdFileName);
  99. static void DisplaySelectCount(void);
  100. static void EnableGOGadget(void);
  101. static short isFile(const struct FSDirEntry *FS);
  102. static void UseDiskObject(struct AppMessage *AppMsg);
  103. static void AddFSEntries(struct AppMessage *AppMsg);
  104. static BOOL isChildOf(const char *Parent, const char *Child);
  105. static size_t InsertFSe(struct FSDir *Dir, struct FSDirEntry *FSe);
  106. static BOOL isInWindow(struct Window *Win, short x, short y);
  107. static void GetPatternGadgetString(void);
  108. static ULONG __interrupt __saveds DisplayFileSizeHookFunc(struct Hook *HookPtr,
  109.         struct FSDirEntry *Record, struct ALVDrawMsg *Msg );
  110. static ULONG __interrupt __saveds DisplayFileProtectionHookFunc(struct Hook *HookPtr,
  111.         struct FSDirEntry *Record, struct ALVDrawMsg *Msg );
  112. static ULONG __interrupt __saveds ClickFileHookFunc(struct Hook *HookPtr,
  113.         struct FSDirEntry *Record, struct ALVDrawMsg *Msg );
  114. static ULONG __interrupt __saveds DisplaySelectHookFunc(struct Hook *HookPtr,
  115.         struct FSDirEntry *Record, struct ALVDrawMsg *Msg );
  116. static ULONG __interrupt __saveds SelectFileHookFunc(struct Hook *HookPtr,
  117.         struct FSDirEntry *Record, struct ALVDrawMsg *Msg );
  118. static BOOL isInFileView(WORD MouseX, WORD MouseY);
  119. static void __interrupt DrawMarkerBox(struct RastPort *rp, short xMin, short xMax, short yMin, short yMax);
  120. static void __interrupt DrawSelectMarker(struct RastPort *rp, short x, short y, short Width,
  121.         const struct FSDirEntry *Record, const struct ALVDrawMsg *Msg);
  122.  
  123.  
  124. // aus Backup.c
  125. extern struct TextFont *myFont, *ScreenFont;
  126. extern struct MsgPort *AppPort;        // Msg Port für AppMessages
  127. extern struct DiskFlags __far *Disks;    /* Laufwerks-Liste */
  128.  
  129. // aus Backup_Window.c
  130. extern struct TextAttr DefaultFAttr;
  131. extern struct Library *AmigaGuideBase;
  132. extern struct Library *GadToolsBase;
  133. extern char BackupScreenTitle[80];    // Screen Title
  134. extern APTR vi;                // VisualInfo
  135. extern struct DrawInfo *myDrawInfo;
  136. extern struct Screen *WBScreen;
  137.  
  138. // aus CmdFile.c
  139. extern FILE *aktCmdFile;        // fp für Kommandofile
  140. extern char __far CmdFileName[FMSIZE];    // Name des Kommandofile
  141.  
  142. // aus FileSelectGadget.c
  143. extern struct TagItem MoreALVTags[];
  144. extern struct Image AssignImage;
  145. extern struct Image VolumeImage;
  146. extern struct Image DrawerImage;
  147.  
  148. // aus Text.c
  149. extern struct Locale *myLocale;
  150.  
  151.  
  152. BOOL HelpActive = FALSE;        // Online-Hilfe ist aktiv
  153. BOOL GadgetHelp = FALSE;        // V39-GadgetHelp ist verfügbar
  154.  
  155. struct Window *activeWindow;        // das gerade aktive Backup-Window
  156.  
  157. struct BackupOptions *BackupOpt = NULL;    // Optionen während der Sicherung
  158.  
  159. ULONG BackupHelpGroup;            // Help Group
  160.  
  161. static MINLIST(FSResourceList);
  162.  
  163. static struct BInputHandler *FSInput = NULL;
  164.  
  165. struct IBox FSWindowPos = { DFLT_LEFT, DFLT_TOP, DFLT_WIDTH, DFLT_HEIGHT };
  166. static struct IBox FSWindowLimits = { DFLT_WIDTH, MIN_FSHEIGHT, MAX_FSWIDTH, MAX_FSHEIGHT };
  167.  
  168. static struct Gadget *FSGList = NULL;
  169. static struct Gadget *FSGadgets[FS_CNT];
  170. static UWORD OffX, OffY;
  171. static ULONG FontX, FontY;
  172.  
  173. static struct GadgetShort *FSGadgetShort;    // Tabelle für Tasten-Kürzel
  174.  
  175. struct Window *MenuWin;            // an diesem Window hängt das Menu
  176. struct Window *FSwin;            // File Select Window
  177.  
  178. static struct AppWindow *myAppWindow = NULL;
  179.  
  180. static struct ScrollingWindow FileDisplayScr;
  181.  
  182. static short InnerWidth, InnerHeight;    // innere Abmessungen des Window
  183.  
  184. static short MouseButtonDown;        // 1, solange linke Maustaste innerhalb der File-Liste gedrückt bleibt
  185.  
  186. static struct FSDir *aktFSDir = NULL;
  187.  
  188. static int *globalFSResult = NULL;    // hier wird beim ersten Füllen des FS-Windows ggf. ein eingabe()-Result abgelegt
  189.                     // zur Weiterverarbeitung in BeginGO()
  190.  
  191. static struct NamePattern SelectPattern = { "#?", "", FALSE };    // zur Auswahl nach Namen
  192. static enum ArchiveSelect FSArchiveSelect = ARCSEL_ignore;    // zur Auswahl nach Archiv-Bit
  193.  
  194. static unsigned long MainFSDirLength = 0L;
  195.  
  196. static unsigned long FSFileSelectCount = 0L;    // Anzahl selektierte Files
  197. static unsigned long FSDirSelectCount = 0L;    // Anzahl selektierte Directories
  198.  
  199. static short GlobalFSStartCode = 0;
  200.  
  201. static MINLIST(SelectRecordsList);
  202. static MINLIST(SubDirRecordsList);
  203.  
  204.  
  205. static struct Hook FSGadgetShortHook =
  206.     {
  207.     { NULL },
  208.     HookEntry,
  209.     (ULONG (*)()) HandleFSGadgetCallback,
  210.     NULL,            // wird (short *)
  211.     };
  212.  
  213. static struct Hook DisplayFileSizeHook =
  214.     {
  215.     { NULL },
  216.     HookEntry,
  217.     (ULONG (*)()) DisplayFileSizeHookFunc,
  218.     NULL,
  219.     };
  220.  
  221. static struct Hook DisplayFileProtectionHook =
  222.     {
  223.     { NULL },
  224.     HookEntry,
  225.     (ULONG (*)()) DisplayFileProtectionHookFunc,
  226.     NULL,
  227.     };
  228.  
  229. static struct Hook DisplaySelectHook =
  230.     {
  231.     { NULL },
  232.     HookEntry,
  233.     (ULONG (*)()) DisplaySelectHookFunc,
  234.     NULL,
  235.     };
  236.  
  237. struct Hook ClickFileHook =
  238.     {
  239.     { NULL },
  240.     HookEntry,
  241.     (ULONG (*)()) ClickFileHookFunc,
  242.     NULL,
  243.     };
  244.  
  245. struct Hook SelectFileHook =
  246.     {
  247.     { NULL },
  248.     HookEntry,
  249.     (ULONG (*)()) SelectFileHookFunc,
  250.     NULL,
  251.     };
  252.  
  253.  
  254. #define    ALV_STDFLAGS    0l
  255.  
  256. struct ALVColumn FileSelectColumns[] =
  257.     {
  258.     // SubDir-Select-Marker
  259.     { NULL, ALVLT_StringPtr, { NULL, 0l, 0l }, ALVAH_HCenter, ALVAV_VCenter,
  260.         ALVLT_User, ALVAH_HCenter, ALVAV_VCenter,
  261.         (size_t) &DisplaySelectHook,
  262.         0, ALV_STDFLAGS,
  263.         &FileSelectColumns[1] },
  264.     // Icon
  265.     { NULL, ALVLT_StringPtr, { NULL, 0l, 0l }, ALVAH_HCenter, ALVAV_VCenter,
  266.         ALVLT_Image, ALVAH_HCenter, ALVAV_VCenter,
  267.         offsetof(struct FSDirEntry, fse_Image), 
  268.         0, ALV_STDFLAGS,
  269.         &FileSelectColumns[2] },
  270.     // Filename
  271.     { NULL, ALVLT_StringPtr, { NULL, 0l, 0l }, ALVAH_HCenter, ALVAV_VCenter,
  272.         ALVLT_String, ALVAH_Left, ALVAV_VCenter,
  273.         offsetof(struct FSDirEntry, fse_Name),
  274.         0, ALV_STDFLAGS,
  275.         &FileSelectColumns[3] },
  276.     // Filegröße
  277.     { NULL, ALVLT_String, { NULL, 0l, 0l }, ALVAH_HCenter, ALVAV_VCenter,
  278.         ALVLT_UserString, ALVAH_Right, ALVAV_VCenter,
  279.         (size_t) &DisplayFileSizeHook,
  280.         0, ALV_STDFLAGS,
  281.         &FileSelectColumns[4] },
  282.     // Protection
  283.     { NULL, ALVLT_String, { NULL, 0l, 0l }, ALVAH_HCenter, ALVAV_VCenter,
  284.         ALVLT_UserString, ALVAH_HCenter, ALVAV_VCenter,
  285.         (size_t) &DisplayFileProtectionHook,
  286.         0, ALV_STDFLAGS,
  287.         &FileSelectColumns[5] },
  288.     // Datum
  289.     { NULL, ALVLT_String, { NULL, 0l, 0l }, ALVAH_HCenter, ALVAV_VCenter,
  290.         ALVLT_Date, ALVAH_Right, ALVAV_VCenter,
  291.         offsetof(struct FSDirEntry, fse_Date), 
  292.         0, ALV_STDFLAGS,
  293.         &FileSelectColumns[6] },
  294.     // Uhrzeit
  295.     { NULL, ALVLT_String, { NULL, 0l, 0l }, ALVAH_HCenter, ALVAV_VCenter,
  296.         ALVLT_Time, ALVAH_Right, ALVAV_VCenter,
  297.         offsetof(struct FSDirEntry, fse_Date), 
  298.         0, ALV_STDFLAGS,
  299.         NULL },
  300.     };
  301.  
  302.  
  303. BOOL getargs(struct BackupOptions *Opts)
  304. {
  305.     int erg = 0;
  306.  
  307.     ASSERT_VALID(Opts);
  308.  
  309.     GlobalFSStartCode = 0;
  310.  
  311.     if (!BeginFileSelect(Opts, &erg))
  312.         return 0;
  313.  
  314.     EnableTapeMenu(Disks[Opts->bo_FirstUnit].TapeReq != NULL);
  315.  
  316.     while (FSwin && GlobalFSStartCode != FS_START && GlobalFSStartCode != FS_ABORT)
  317.         {
  318.         eingabe(0l);
  319.         }
  320.         
  321.     CloseXGO(GlobalFSStartCode);
  322.     EndFileSelect();
  323.  
  324.     return (BOOL) (FS_START == GlobalFSStartCode);
  325. }
  326.  
  327.  
  328. static UWORD ComputeX( UWORD value )
  329. {
  330.     return ((UWORD) ((value * FontX) / 65535));
  331. }
  332.  
  333.  
  334. static UWORD ComputeY( UWORD value )
  335. {
  336.     return ((UWORD) ((value * FontY) / 65535));
  337. }
  338.  
  339.  
  340. // Prüfung, ob <addr> im ROM liegt
  341. static short inROM(APTR addr)
  342. {
  343.     return (short)(addr >= (APTR) 0xf80000 && addr <= (APTR) 0xffffff);
  344. }
  345.  
  346. void InitFileSelect(struct BackupOptions *Opts)
  347. {
  348.     ASSERT_VALID(Opts);
  349.     BackupOpt = Opts;
  350.  
  351.     if (BackupOpt->bo_FSDirList == NULL)
  352.         BackupOpt->bo_FSDirCount = 0;
  353. }
  354.  
  355.  
  356. static void FSRender( void )
  357. {
  358.     DrawBevelBox( FSwin->RPort, OffX + ComputeX(3), OffY + ComputeY(2),
  359.             ComputeX( 372 ),
  360.             ComputeY( 62 ),
  361.             GT_VisualInfo, vi,
  362.             GTBB_Recessed, TRUE,
  363.             TAG_DONE );
  364. }
  365.  
  366.  
  367. static void InitFS(void)
  368. {
  369.     static BOOL First = TRUE;
  370.     UWORD lc, tc;
  371.     struct Gadget *g;
  372.  
  373.     CreateGadgetShort(&FSGadgetShort);
  374.  
  375.     if (FSGList)
  376.         {
  377.         if (FSwin)
  378.             RemoveGList(FSwin, FSGList, -1);
  379.  
  380.         FreeGadgets(FSGList);
  381.         FSGList = NULL;
  382.  
  383.         FreeBResources(&FSResourceList);
  384.         }
  385.  
  386.     if (First)
  387.         {
  388.         FSWindowLimits.Left = ComputeX(DFLT_WIDTH) + OffX + WBScreen->BarHeight;
  389.         FSWindowLimits.Top = ComputeY(MIN_FSHEIGHT);
  390.         FSWindowLimits.Width =     max(MAX_FSWIDTH, (( FileDisplayScr.sFont->tf_XSize * MAX_FSWIDTH) + 4 ) / 8);
  391.  
  392.         // Window-Größe begrenzen
  393.         // ACHTUNG: FSWindowPos ist InnerHeight und InnerWidth !
  394.         FSWindowPos.Width = min(FSWindowLimits.Width - OffX - WBScreen->BarHeight,
  395.                 max(FSWindowLimits.Left - OffX - WBScreen->BarHeight, FSWindowPos.Width));
  396.         FSWindowPos.Height = max(FSWindowLimits.Top - OffY - WBScreen->WBorBottom, FSWindowPos.Height);
  397.  
  398.         FSGadgetOff[GDX_FSHelpGadget].Left     = DFLT_WIDTH  - FSNGad[GDX_FSHelpGadget].ng_LeftEdge;
  399.         FSGadgetOff[GDX_FSGlobOptGadget].Left  = DFLT_WIDTH  - FSNGad[GDX_FSGlobOptGadget].ng_LeftEdge;
  400.         FSGadgetOff[GDX_FSALVGadget].Width     = DFLT_WIDTH  - FSNGad[GDX_FSALVGadget].ng_Width;
  401.         FSGadgetOff[GDX_FSALVGadget].Height    = DFLT_HEIGHT - FSNGad[GDX_FSALVGadget].ng_Height;
  402.         FSGadgetOff[GDX_FSDrawerGadget].Width  = DFLT_WIDTH  - FSNGad[GDX_FSDrawerGadget].ng_Width;
  403.         FSGadgetOff[GDX_FSStartGadget].Top     = DFLT_HEIGHT - FSNGad[GDX_FSStartGadget].ng_TopEdge;
  404.         FSGadgetOff[GDX_FSParentGadget].Top    = DFLT_HEIGHT - FSNGad[GDX_FSParentGadget].ng_TopEdge;
  405.         FSGadgetOff[GDX_FSVolumesGadget].Top   = DFLT_HEIGHT - FSNGad[GDX_FSVolumesGadget].ng_TopEdge;
  406.         FSGadgetOff[GDX_FSRereadGadget].Top    = DFLT_HEIGHT - FSNGad[GDX_FSRereadGadget].ng_TopEdge;
  407.         FSGadgetOff[GDX_FSCancelGadget].Top    = DFLT_HEIGHT - FSNGad[GDX_FSCancelGadget].ng_TopEdge;
  408.         }
  409.  
  410.     // Texte für Cycle-Gadgets vorbereiten
  411.     FSArcSetGadget0Labels[0] = (STRPTR) GetString(MSG_ARCSET_IGNORE_GAD);
  412.     FSArcSetGadget0Labels[1] = (STRPTR) GetString(MSG_ARCSET_RESET_GAD);
  413.     FSArcSetGadget0Labels[2] = (STRPTR) GetString(MSG_ARCSET_SET_GAD);
  414.  
  415.     MoreALVTags[0].ti_Data = (ULONG) myLocale;
  416.  
  417.     if ( ! ( g = CreateContext( &FSGList )))
  418.         {
  419.         alarm(GetString(MSG_CREATECONTEXT_FAIL), __FUNC__);
  420.         myabort(20);
  421.         }
  422.  
  423.     for( lc = 0, tc = 0; lc < FS_CNT; lc++ )
  424.         {
  425.         struct NewGadget ng;
  426.  
  427.         ng = FSNGad[lc];
  428.  
  429.         // Korrekturen für andere Window-Größen (nicht default)
  430.         if (FSGadgetOff[lc].Left)
  431.             ng.ng_LeftEdge = OffX + FSWindowPos.Width - ComputeX(FSGadgetOff[lc].Left);
  432.         else
  433.             ng.ng_LeftEdge   = OffX + ComputeX( ng.ng_LeftEdge );
  434.  
  435.         if (FSGadgetOff[lc].Top)
  436.             ng.ng_TopEdge = OffY + FSWindowPos.Height - ComputeY(FSGadgetOff[lc].Top);
  437.         else
  438.             ng.ng_TopEdge    = OffY + ComputeY( ng.ng_TopEdge );
  439.  
  440.         if (GENERIC_KIND != FSGTypes[lc])
  441.             {
  442.             // Gadgets GENERIC_KIND werden nicht skaliert!
  443.             if (FSGadgetOff[lc].Width)
  444.                 ng.ng_Width = FSWindowPos.Width - ComputeX(FSGadgetOff[lc].Width);
  445.             else
  446.                 ng.ng_Width      = ComputeX( ng.ng_Width );
  447.  
  448.             if (FSGadgetOff[lc].Height)
  449.                 ng.ng_Height = FSWindowPos.Height - ComputeY(FSGadgetOff[lc].Height);
  450.             else
  451.                 ng.ng_Height     = ComputeY( ng.ng_Height);
  452.             }
  453.  
  454.         // bei GENRIC_KIND und IMAGEBUTTON_KIND Gadgets hat ng_GadgetText eine besondere Bedeutung!
  455.         if (GENERIC_KIND != FSGTypes[lc] && IMAGEBUTTON_KIND != FSGTypes[lc])
  456.             {
  457.             if (ng.ng_GadgetText)
  458.                 ng.ng_GadgetText = (STRPTR) GetString((long) ng.ng_GadgetText);
  459.             }
  460.  
  461.         ng.ng_VisualInfo = vi;
  462.  
  463.         if (NULL == ng.ng_TextAttr)
  464.             ng.ng_TextAttr = WBScreen->Font;
  465.  
  466.         switch (FSGTypes[lc])
  467.             {
  468.         case GENERIC_KIND:
  469.             {
  470.             struct GenericGadgetImages *gImg = (struct GenericGadgetImages *) ng.ng_GadgetText;
  471.  
  472.             ng.ng_GadgetText = NULL;
  473.             if (gImg)
  474.                 {
  475.                 // Breite + Höhe des Gadgets von den Images übernehmen
  476.                 ng.ng_Width = gImg->gi_Render->Width;
  477.                 ng.ng_Height = gImg->gi_Render->Height;
  478.                 }
  479.             FSGadgets[lc] = g = CreateGadgetA((ULONG)FSGTypes[ lc ], g, 
  480.                     &ng, (struct TagItem *) &FSGTags[ tc ]);
  481.             if (g)
  482.                 {
  483.                 g->GadgetType |= GTYP_BOOLGADGET;
  484.                 g->Flags |= GFLG_GADGHIMAGE | GFLG_GADGIMAGE;
  485.                 g->Activation = GACT_RELVERIFY;
  486.                 g->GadgetRender = gImg->gi_Render;
  487.                 g->SelectRender = gImg->gi_Selected;
  488.                 }
  489.  
  490.             if (ng.ng_GadgetText)
  491.                 EnterGadgetShort(&ng, FSGTypes[lc], &FSGTags[ tc ], g, FSGadgetShort);
  492.             }
  493.             break;
  494.  
  495.         case ALVGAD_KIND:
  496.             FSGadgets[lc] = g = 
  497.                     CreateALVGad(&ng,
  498.                         GA_Previous, g,
  499.                         TAG_MORE, &FSGTags[tc],
  500.                         TAG_END);
  501.             if (g)
  502.                 RememberBResource(BRES_ALVGADGET, g, &FSResourceList);
  503.             break;
  504.  
  505.         case IMAGEBUTTON_KIND:
  506.             {
  507.             struct GenericGadgetImages *gImg = (struct GenericGadgetImages *) ng.ng_GadgetText;
  508.             struct Image *RenderImage, *SelectedImage;
  509.  
  510.             ng.ng_GadgetText = NULL;
  511.  
  512.             // Skalierte Images erzeugen
  513.             RenderImage = ScaleImage(gImg->gi_Render, ng.ng_Width, ng.ng_Height);
  514.             if (RenderImage)
  515.                 RememberBResource(BRES_SCALEDIMAGE, RenderImage, &FSResourceList);
  516.  
  517.             SelectedImage = ScaleImage(gImg->gi_Selected, ng.ng_Width, ng.ng_Height);
  518.             if (SelectedImage)
  519.                 RememberBResource(BRES_SCALEDIMAGE, SelectedImage, &FSResourceList);
  520.  
  521.             if (RenderImage && SelectedImage)
  522.                 {
  523.                 FSGadgets[lc] = g = CreateGadgetA(GENERIC_KIND, g, &ng, (struct TagItem *) &FSGTags[tc]);
  524.                 if (g)
  525.                     {
  526.                     g->GadgetType |= GTYP_BOOLGADGET;
  527.                     g->Activation = GACT_RELVERIFY;
  528.                     if (gImg)
  529.                         {
  530.                         g->Flags |= GFLG_GADGHIMAGE | GFLG_GADGIMAGE;
  531.                         g->GadgetRender = RenderImage;
  532.                         g->SelectRender = SelectedImage;
  533.                         }
  534.                     }
  535.                 }
  536.             }
  537.             break;
  538.         default:
  539.             FSGadgets[lc] = g = CreateGadgetA((ULONG)FSGTypes[ lc ], g, 
  540.                     &ng, (struct TagItem *)&FSGTags[tc] );
  541.             
  542.             if (ng.ng_GadgetText)
  543.                 EnterGadgetShort(&ng, FSGTypes[lc], &FSGTags[ tc ], g, FSGadgetShort);
  544.             break;
  545.             }
  546.  
  547.         while( FSGTags[ tc ] ) tc += 2;
  548.         tc++;
  549.  
  550.         if (NULL == g)
  551.             {
  552.             alarm(GetString(MSG_CREATEGAD_FAILED), __FUNC__);
  553.             myabort(20);
  554.             }
  555.         }
  556.  
  557.     if (FSwin)
  558.         {
  559.         // erzeugte Gadgets einhängen wenn FSwin offen!
  560.         RefreshWindowFrame(FSwin);
  561.         AddGList(FSwin, FSGList, ~0, ~0, NULL);
  562.         RefreshGList(FSGList, FSwin, NULL, ~0);
  563.         GT_RefreshWindow(FSwin, NULL);
  564.         }
  565.  
  566.     // kein Online Help ohne AmigaGuide!
  567.     GT_SetGadgetAttrs(FSGadgets[GDX_FSHelpGadget], FSwin, NULL,
  568.         GA_Disabled, NULL == AmigaGuideBase,
  569.         TAG_END);
  570.  
  571.     GT_SetGadgetAttrs(FSGadgets[GDX_FSPatternGadget], FSwin, NULL,
  572.         GTST_String, SelectPattern.RawName,
  573.         TAG_END);
  574.  
  575.     if (aktFSDir)
  576.         {
  577.         GT_SetGadgetAttrs(FSGadgets[GDX_FSDrawerGadget], FSwin, NULL,
  578.             GTST_String, aktFSDir->fsd_Name,
  579.             TAG_END);
  580.         SetGadgetAttrs(FSGadgets[GDX_FSALVGadget], FSwin, NULL,
  581.             ALV_Records, (aktFSDir && aktFSDir->fsd_DirCount) ? aktFSDir->fsd_EntryList[0] : NULL,
  582.             TAG_END);
  583.         }
  584.  
  585.     if (First && !SetupFSMenu())
  586.         return;
  587.  
  588.     SetupBackupOpts(BackupOpt, "");
  589.  
  590.     First = FALSE;
  591. }
  592.  
  593.  
  594. static BOOL BeginFileSelect(struct BackupOptions *Opts, int *FSResult)
  595. {
  596.     ASSERT_VALID(Opts);
  597.  
  598.     if (FSwin)
  599.         return FALSE;
  600.  
  601.     *FSResult = 0;
  602.     globalFSResult = FSResult;
  603.  
  604.     CalcGadgetScale(WBScreen, ScreenFont, &FontX, &FontY, &OffX, &OffY, 8, 11);
  605.  
  606.     InitFileSelect(Opts);
  607.  
  608.     GadgetHelp = IntuitionBase->LibNode.lib_Version >= 39;
  609.     if (GadgetHelp)
  610.         BackupHelpGroup = GetUniqueID();    // V39!
  611.  
  612.     SetFSListFont(Opts);
  613.     InitFS();
  614.  
  615.     FSwin = OpenWindowTags(NULL,
  616.             WA_Left,    FSWindowPos.Left,
  617.             WA_Top,        FSWindowPos.Top,
  618.             WA_InnerWidth,    FSWindowPos.Width,
  619.             WA_InnerHeight,    FSWindowPos.Height,
  620.             WA_IDCMP,    STRINGIDCMP | BUTTONIDCMP | CYCLEIDCMP
  621.                 | CHECKBOXIDCMP | SCROLLERIDCMP | ARROWIDCMP
  622.                 | IDCMP_NEWSIZE | IDCMP_MENUPICK
  623.                 | IDCMP_RAWKEY | IDCMP_ACTIVEWINDOW | IDCMP_VANILLAKEY
  624.                 | IDCMP_MENUHELP | IDCMP_REFRESHWINDOW
  625.                 | IDCMP_GADGETHELP | IDCMP_IDCMPUPDATE,
  626.             WA_Flags,    WFLG_SIZEGADGET | WFLG_DRAGBAR | WFLG_DEPTHGADGET
  627.                 |WFLG_SMART_REFRESH|WFLG_ACTIVATE,
  628.             WA_Gadgets,    FSGList,
  629.             WA_NewLookMenus, TRUE,
  630.             WA_MenuHelp,    TRUE,
  631.             WA_AutoAdjust,    TRUE,
  632.             WA_HelpGroup,     BackupHelpGroup,
  633.             WA_ScreenTitle,    BackupScreenTitle,
  634.             WA_PubScreen,    WBScreen,
  635.             TAG_END);
  636.  
  637.     if (NULL == FSwin)
  638.         {
  639.         alarm(GetString(MSG_CANNOT_OPEN_WINDOW), __FUNC__, "FSWin");
  640.         return FALSE;
  641.         }
  642.  
  643.     GT_RefreshWindow(FSwin, NULL);
  644.  
  645.     WindowLimits(FSwin, FSWindowLimits.Left,
  646.         FSWindowLimits.Top, FSWindowLimits.Width,
  647.         MAX_FSHEIGHT);
  648.  
  649.     FSRender();
  650.  
  651.     if (AppPort)
  652.         {
  653.         myAppWindow = AddAppWindowA(AMID_FILESELECT, (ULONG) FSwin,
  654.                     FSwin, AppPort, NULL);
  655.         }
  656.  
  657.     // myFont einstellen
  658.     if (myFont)
  659.         SetFont(FSwin->RPort, myFont);
  660.  
  661.     FSInput = AddBInputHandler(1L << FSwin->UserPort->mp_SigBit, HandleFSMsg);
  662.  
  663.     MenuWin = FSwin;
  664.     SetMenuStrip(FSwin, FSMenuList);
  665.  
  666.     if (FSwin->Width - FSwin->BorderLeft - FSwin->BorderRight != FSWindowPos.Width
  667.             || FSwin->Height - FSwin->BorderTop - FSwin->BorderBottom != FSWindowPos.Height)
  668.         {
  669.         // Window paßte nicht auf den Schirm und wurde vom System verkleinert!
  670.         SizeFSWindow(WSC_SizeAdjusted);
  671.         }
  672.     else
  673.         SizeFSWindow(WSC_SameSize);
  674.     
  675.     SetMenus(BackupOpt);
  676.  
  677.     DisplaySelectCount();
  678.  
  679.     if (NULL == aktFSDir)
  680.         GetFSDir(Opts->bo_CurrentDir, NULL);
  681.  
  682.     ((struct Process*) FindTask(NULL))->pr_WindowPtr = FSwin;
  683.  
  684.     return TRUE;
  685. }
  686.  
  687.  
  688. static void EndFileSelect(void)
  689. {
  690.     EndByteCount();
  691.  
  692.     RemBInputHandler(&FSInput);
  693.  
  694.     if (myAppWindow)
  695.         {
  696.         struct AppMessage *AppMsg;
  697.  
  698.         // Message Port leeren !
  699.         while (AppMsg = (struct AppMessage *) GetMsg(AppPort) )
  700.             ReplyMsg((struct Message *) AppMsg);
  701.  
  702.         RemoveAppWindow(myAppWindow);
  703.         myAppWindow = NULL;
  704.         }
  705.  
  706.     if (FSwin)
  707.         {
  708.         ((struct Process*) FindTask(NULL))->pr_WindowPtr = NULL;
  709.  
  710.         if (MenuWin == FSwin)
  711.             {
  712.             ClearMenuStrip(MenuWin);
  713.             MenuWin = NULL;
  714.             }
  715.  
  716.         SafeCloseWindow(&FSwin);
  717.         }
  718.  
  719.     if (FSMenuList)
  720.         {
  721.         FreeMenus(FSMenuList);
  722.         FSMenuList = NULL;
  723.         }
  724.     if (FSGList)
  725.         {
  726.         FreeGadgets(FSGList);
  727.         FSGList = NULL;
  728.         }
  729.  
  730.     FreeBResources(&FSResourceList);
  731.  
  732.     if (FileDisplayScr.sFont)
  733.         {
  734.         CloseFont(FileDisplayScr.sFont);
  735.         FileDisplayScr.sFont = NULL;
  736.         }
  737.  
  738.     DestroyGadgetShort(&FSGadgetShort);
  739. }
  740.  
  741.  
  742. void CleanUpFS(void)
  743. {
  744.     struct FSDir *dir;
  745.     unsigned long n;
  746.  
  747.     EndFileSelect();
  748.  
  749.     if (BackupOpt && BackupOpt->bo_FSDirList)
  750.         {
  751.         for (n=0; n<BackupOpt->bo_FSDirCount; n++)
  752.             {
  753.             dir = BackupOpt->bo_FSDirList[n];
  754.             if (dir)
  755.                 {
  756.                 EmptyFSDir(dir);
  757.                 if (dir->fsd_ListSize)
  758.                     {
  759.                     free(dir->fsd_EntryList);
  760.                     }
  761.                 dir->fsd_ListSize = 0;
  762.                 if (dir->fsd_Name)
  763.                     free(dir->fsd_Name);
  764.                 free(dir);
  765.                 BackupOpt->bo_FSDirList[n] = NULL;
  766.                 }
  767.             }
  768.         free(BackupOpt->bo_FSDirList);
  769.         BackupOpt->bo_FSDirList = NULL;
  770.         MainFSDirLength = 0L;
  771.         BackupOpt->bo_FSDirCount = 0L;
  772.         }
  773. }
  774.  
  775.  
  776. // AppMessage behandeln, in am_UserData ist das jeweilige Window eingetragen
  777. int HandleAppMsg(void)
  778. {
  779.     struct AppMessage *AppMsg;
  780.     struct Window *AppMsgWindow;
  781.  
  782.     while ((AppMsg = (struct AppMessage *) GetMsg(AppPort)) != NULL)
  783.         {
  784.         AppMsgWindow = NULL;
  785.  
  786.         if (AppMsg->am_Version == AM_VERSION)
  787.             {
  788.             switch (AppMsg->am_Type)
  789.                 {
  790.             case AMTYPE_APPWINDOW:
  791.                 AppMsgWindow = (struct Window *) AppMsg->am_UserData;
  792.                 UseDiskObject(AppMsg);
  793.                 break;
  794.  
  795.             case AMTYPE_APPICON:
  796.                 if (0 == AppMsg->am_NumArgs)
  797.                     {
  798.                     // Doppelklick auf AppIcon
  799.                     SignalUnIconifyMainWindow();
  800.                     }
  801.                 break;
  802.                 }
  803.             }
  804.  
  805.         ReplyMsg((struct Message *) AppMsg);
  806.  
  807.         if (AppMsgWindow)
  808.             ActivateWindow(AppMsgWindow);
  809.         }
  810.  
  811.     return FALSE;
  812. }
  813.  
  814.  
  815. static int HandleFSMsg(void)
  816. {
  817.     struct IntuiMessage *msg;
  818.     int result;
  819.     short *abortFSRead;
  820.  
  821.     abortFSRead = FSGadgetShortHook.h_Data;
  822.  
  823.     while (FSwin && (msg = GT_GetIMsg(FSwin->UserPort)) )
  824.         result = FS_IDCMPHandler(msg, abortFSRead);
  825.  
  826.     if (FSwin)
  827.         DisplaySelectCount();
  828.  
  829.     return result;
  830. }
  831.  
  832.  
  833. static int FS_IDCMPHandler(struct IntuiMessage *msg, short *abortFSRead)
  834. {
  835.     ULONG class;
  836.     USHORT code, qualifier;
  837.     int result = FS_NOTHING;
  838.     struct Gadget *curgadget;
  839.  
  840.     ASSERT_VALID(msg);
  841.     class = msg->Class;
  842.     code = msg->Code;
  843.     qualifier = msg->Qualifier;
  844.     curgadget = (struct Gadget *)msg->IAddress;
  845.  
  846.     GT_ReplyIMsg(msg);
  847.  
  848.     if (FSwin->ReqCount)
  849.         return result;
  850.  
  851.     switch (class)
  852.         {
  853.     case IDCMP_ACTIVEWINDOW:
  854.         d(printf("IDCMP_ACTIVEWINDOW\n"));
  855.         if (MenuWin)
  856.             ClearMenuStrip(MenuWin);
  857.         activeWindow = MenuWin = FSwin;
  858.         ResetMenuStrip(FSwin, FSMenuList);
  859.  
  860.         SetHelpPointer(activeWindow, HelpActive);
  861.         break;
  862.  
  863.     case IDCMP_NEWSIZE:
  864.         d(printf("IDCMP_NEWSIZE\n"));
  865.         SizeFSWindow(WSC_SizeChanged);
  866.         break;
  867.  
  868.     case IDCMP_VANILLAKEY:
  869.         d(printf("IDCMP_VANILLAKEY\n"));
  870.  
  871.         result = HandleGadgetShort(FSGadgetShort, FSwin, code, &FSGadgetShortHook);
  872.         break;
  873.  
  874.     case IDCMP_GADGETHELP:
  875.         d(printf("IDCMP_GADGETHELP\n"));
  876.         if (curgadget == NULL)
  877.             {
  878.             // Nicht über unserem Window
  879.             }
  880.         else if ((APTR) curgadget == (APTR) FSwin)
  881.             {
  882.             // über unserem Window
  883.             CallHelp(HELPID_FSWINDOW_OUTSIDE, TRUE);    // im FSWindow
  884.             }
  885.         else
  886.             HandleFSGadgetHelp(curgadget, code);
  887.         break;
  888.  
  889.     case IDCMP_MENUHELP:
  890.         d(printf("IDCMP_MENUHELP\n"));
  891.         result = ProcessFSMenuHelp(code);
  892.         break;
  893.  
  894.     case IDCMP_GADGETUP:
  895.         d(printf("IDCMP_GADGETUP\n"));
  896.         if (HelpActive && !GadgetHelp)
  897.             HandleFSGadgetHelp(curgadget, code);
  898.         else
  899.             {
  900.             result = HandleFSGadget(curgadget, code, abortFSRead);
  901.             }
  902.         break;
  903.  
  904.     case IDCMP_IDCMPUPDATE:
  905.         switch (code)
  906.             {
  907.         case IDCMPCODE_SELECTRECORD:
  908.             {
  909.             struct FSSelectedRecord *FSS;
  910.  
  911.             FSS = (struct FSSelectedRecord *) RemHead((struct List *) &SelectRecordsList);
  912.             if (FSS)
  913.                 {
  914.                 if (FSS->fsr_Record->fse_fsRecord.alr_Flags & ALRF_SELECTED)
  915.                     InternalSelectEntry(aktFSDir, FSS->fsr_Record, TRUE, TRUE, 0, TRUE);
  916.                 else
  917.                     InternalSelectEntry(aktFSDir, FSS->fsr_Record, FALSE, TRUE, 0, TRUE);
  918.  
  919.                 free(FSS);
  920.                 }
  921.             }
  922.             break;
  923.             }
  924.         break;
  925.  
  926.     case IDCMP_INTUITICKS:
  927.         {
  928.         // bei einem Mausklick auf ein Drawer-Icon wird an die <SubDirRecordsList> ein Eintrag angehängt
  929.         // leider wird dabei keine direkte Benachrichtigung geschickt.
  930.         // Deshalb wird die <SubDirRecordsList> bei jeden INTUITICK gepollt - Nicht schön, aber funktional!
  931.         struct FSSelectedRecord *FSS;
  932.  
  933.         do    {
  934.             FSS = (struct FSSelectedRecord *) RemHead((struct List *) &SubDirRecordsList);
  935.             d(kprintf(__FUNC__ "/%ld: FSS=%08lx\n", __LINE__, FSS));
  936.  
  937.             if (FSS)
  938.                 {
  939.                 // Dir. wechseln
  940.                 if (abortFSRead)
  941.                     *abortFSRead = TRUE;
  942.                 FSSubDir(FSS->fsr_Record);
  943.                 free(FSS);
  944.                 }
  945.             } while (FSS);
  946.         }
  947.         break;
  948.  
  949.     case IDCMP_MENUPICK:
  950.         d(printf("IDCMP_MENUPICK\n"));
  951.         result = ProcessFSMenu(code, BackupOpt);
  952.         break;
  953.  
  954.     case IDCMP_RAWKEY:
  955.         d(printf("IDCMP_RAWKEY\n"));
  956.         if (GADCODE_HELP == code)
  957.             ToggleHelp();
  958.         else
  959.             ScrollFSWindow(code, qualifier);
  960.         break;
  961.  
  962.     case IDCMP_REFRESHWINDOW:
  963.         d(printf("IDCMP_REFRESHWINDOW\n"));
  964.         // This handling is REQUIRED with GadTools.
  965.         GT_BeginRefresh(FSwin);
  966.         GT_EndRefresh(FSwin, TRUE);
  967.         break;
  968.  
  969.     default:
  970.         d(printf("IDCMP=%08lx\n", class));
  971.         break;
  972.         }
  973.  
  974.     if ((GlobalFSStartCode == FS_ABORT) || (GlobalFSStartCode == FS_START))
  975.         EndFileSelect();
  976.  
  977.     return result;
  978. }
  979.  
  980.  
  981. static void __interrupt HandleFSGadgetCallback(struct Hook *hook, struct Gadget *Gad, ULONG *Code)
  982. {
  983.     short *abortFSRead = (short *) hook->h_Data;
  984.  
  985.     HandleFSGadget(Gad, (USHORT) *Code, abortFSRead);
  986. }
  987.  
  988.  
  989. static void HandleFSGadgetHelp(const struct Gadget *gad, USHORT code)
  990. {
  991.     ASSERT_VALID(gad);
  992.     if ((!GadgetHelp && gad->GadgetID == GD_FSHelpGadget) ||
  993.             ((gad->GadgetType & GTYP_GTYPEMASK) == GTYP_STRGADGET
  994.              && code == GADCODE_HELP) )
  995.         {
  996.         StopHelp();
  997.         }
  998.     else if (!(gad->GadgetType & GTYP_SYSGADGET))
  999.         CallHelp(gad->GadgetID, TRUE);
  1000. }
  1001.  
  1002.  
  1003. static short HandleFSGadget(struct Gadget *gad, USHORT code, short *abortFSRead)
  1004. {
  1005.     struct NamePattern Pat;
  1006.     short result = FS_NOTHING;
  1007.  
  1008.     ASSERT_VALID(gad);
  1009.     Pat.isParsed = FALSE;
  1010.  
  1011.     switch (gad->GadgetID)
  1012.         {
  1013.     case GD_FSALVGadget:
  1014.         break;
  1015.  
  1016.     case GD_FSPatternGadget:
  1017.         if (HandleStrGadCode(code))
  1018.             GetPatternGadgetString();
  1019.         break;
  1020.  
  1021.     case GD_FSSelectAttrGadget:
  1022.         SelectFSAttr(TRUE);
  1023.         break;
  1024.  
  1025.     case GD_FSDeselectAttrGadget:
  1026.         SelectFSAttr(FALSE);
  1027.         break;
  1028.  
  1029.     case GD_FSArcSetGadget:
  1030.         FSArchiveSelect = code;
  1031.         break;
  1032.  
  1033.     case GD_FSDrawerGadget:
  1034.         if (HandleStrGadCode(code))
  1035.             {
  1036.             if (abortFSRead)
  1037.                 *abortFSRead = TRUE;
  1038.             GT_SetGadgetAttrs(FSGadgets[GDX_FSParentGadget], FSwin, NULL,
  1039.                 GA_Disabled, FALSE,
  1040.                 TAG_END);
  1041.             GetFSDir(GADSTRING(gad), NULL);
  1042.             }
  1043.         break;
  1044.  
  1045.     case GD_FSSwapDateGadget:
  1046.         SwapFromToDate(FSwin, FSGadgets[GDX_FSFromDateGadget],
  1047.             FSGadgets[GDX_FSToDateGadget]);
  1048.         break;
  1049.  
  1050.     case GD_FSStartGadget:
  1051.         if (FSFileSelectCount || FSDirSelectCount || aktCmdFile)
  1052.             {
  1053.             if (abortFSRead)
  1054.                 *abortFSRead = TRUE;
  1055.             GlobalFSStartCode = FS_START;
  1056.             }
  1057.         else
  1058.             alarm(GetString(MSG_NOTHING_SELECTED));
  1059.         break;
  1060.  
  1061.     case GD_FSVolumesGadget:
  1062.         if (abortFSRead)
  1063.             *abortFSRead = TRUE;
  1064.         aktFSDir = GetVolumes();
  1065.         GT_SetGadgetAttrs(FSGadgets[GDX_FSParentGadget], FSwin, NULL,
  1066.             GA_Disabled, TRUE,
  1067.             TAG_END);
  1068.         GT_SetGadgetAttrs(FSGadgets[GDX_FSDrawerGadget], FSwin, NULL,
  1069.             GTST_String, aktFSDir->fsd_Name,
  1070.             TAG_END);
  1071.         DisplayFSList(aktFSDir);
  1072.         break;
  1073.  
  1074.     case GD_FSFromDateGadget:
  1075.     case GD_FSToDateGadget:
  1076.         HandleStrGadCode(code);
  1077.         break;
  1078.  
  1079.     case GD_FSFromOnGadget:
  1080.         GT_SetGadgetAttrs(FSGadgets[GDX_FSFromDateGadget], FSwin, NULL,
  1081.             GA_Disabled, !code,
  1082.             TAG_END);
  1083.         break;
  1084.  
  1085.     case GD_FSToOnGadget:
  1086.         GT_SetGadgetAttrs(FSGadgets[GDX_FSToDateGadget], FSwin, NULL,
  1087.             GA_Disabled, !code,
  1088.             TAG_END);
  1089.         break;
  1090.  
  1091.     case GD_FSParentGadget:
  1092.         if (abortFSRead)
  1093.             *abortFSRead = TRUE;
  1094.         FSParentDir();
  1095.         break;
  1096.  
  1097.     case GD_FSCancelGadget:
  1098.         if (abortFSRead)
  1099.             *abortFSRead = TRUE;
  1100.         GlobalFSStartCode = FS_ABORT;
  1101.         break;
  1102.  
  1103.     case GD_FSRereadGadget:
  1104.         if (aktFSDir)
  1105.             {
  1106.             if (aktFSDir->fsd_isVolList)
  1107.                 {
  1108.                 aktFSDir = GetVolumes();
  1109.                 DisplayFSList(aktFSDir);
  1110.                 }
  1111.             else
  1112.                 aktFSDir = ReadFSDir(aktFSDir->fsd_Name, aktFSDir, NULL);
  1113.             }
  1114.         break;
  1115.  
  1116.     case GD_FSGlobOptGadget:
  1117. //???        SelectGadget(&FSWinGOGadget, FSwin, NULL, TRUE);
  1118.         GT_SetGadgetAttrs(FSGadgets[GDX_FSGlobOptGadget], FSwin, NULL,
  1119.             GA_Disabled, TRUE,
  1120.             TAG_END);
  1121.         BeginXGO(FSwin, BackupOpt);
  1122.         break;
  1123.  
  1124.     case GD_FSHelpGadget:
  1125.         ToggleHelp();
  1126.         break;
  1127.  
  1128.     default:
  1129.         if (isascii(gad->GadgetID))
  1130.             result = gad->GadgetID;
  1131.         break;
  1132.         }
  1133.  
  1134.     return result;
  1135. }
  1136.  
  1137.  
  1138. static void ScrollFSWindow(USHORT Code, USHORT Qualifier)
  1139. {
  1140.     if (Code == GADCODE_UP)
  1141.         {
  1142.         if (Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT))
  1143.             {
  1144.             SetGadgetAttrs(FSGadgets[GDX_FSALVGadget], FSwin, NULL,
  1145.                 ALV_ScrollUp, ALV_PAGE_SCROLL,
  1146.                 TAG_END);
  1147.             }
  1148.         else if (Qualifier & IEQUALIFIER_CONTROL)
  1149.             {
  1150.             SetGadgetAttrs(FSGadgets[GDX_FSALVGadget], FSwin, NULL,
  1151.                 ALV_TopLine, 0,
  1152.                 TAG_END);
  1153.             }
  1154.         else
  1155.             {
  1156.             SetGadgetAttrs(FSGadgets[GDX_FSALVGadget], FSwin, NULL,
  1157.                 ALV_ScrollUp, 1,
  1158.                 TAG_END);
  1159.             }
  1160.         }
  1161.     else if (Code == GADCODE_DOWN)
  1162.         {
  1163.         if (Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT))
  1164.             {
  1165.             SetGadgetAttrs(FSGadgets[GDX_FSALVGadget], FSwin, NULL,
  1166.                 ALV_ScrollDown, ALV_PAGE_SCROLL,
  1167.                 TAG_END);
  1168.             }
  1169.         else if (Qualifier & IEQUALIFIER_CONTROL)
  1170.             {
  1171.             SetGadgetAttrs(FSGadgets[GDX_FSALVGadget], FSwin, NULL,
  1172.                 ALV_TopLine, ULONG_MAX,
  1173.                 TAG_END);
  1174.             }
  1175.         else
  1176.             {
  1177.             SetGadgetAttrs(FSGadgets[GDX_FSALVGadget], FSwin, NULL,
  1178.                 ALV_ScrollDown, 1,
  1179.                 TAG_END);
  1180.             }
  1181.         }
  1182.     else if (Code == GADCODE_LEFT)
  1183.         {
  1184.         if (Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT))
  1185.             {
  1186.             SetGadgetAttrs(FSGadgets[GDX_FSALVGadget], FSwin, NULL,
  1187.                 ALV_ScrollLeft, ALV_PAGE_SCROLL,
  1188.                 TAG_END);
  1189.             }
  1190.         else if (Qualifier & IEQUALIFIER_CONTROL)
  1191.             {
  1192.             SetGadgetAttrs(FSGadgets[GDX_FSALVGadget], FSwin, NULL,
  1193.                 ALV_LeftPixelOffset, 0,
  1194.                 TAG_END);
  1195.             }
  1196.         else
  1197.             {
  1198.             SetGadgetAttrs(FSGadgets[GDX_FSALVGadget], FSwin, NULL,
  1199.                 ALV_ScrollLeft, 1,
  1200.                 TAG_END);
  1201.             }
  1202.         }
  1203.     else if (Code == GADCODE_RIGHT)
  1204.         {
  1205.         if (Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT))
  1206.             {
  1207.             SetGadgetAttrs(FSGadgets[GDX_FSALVGadget], FSwin, NULL,
  1208.                 ALV_ScrollRight, ALV_PAGE_SCROLL,
  1209.                 TAG_END);
  1210.             }
  1211.         else if (Qualifier & IEQUALIFIER_CONTROL)
  1212.             {
  1213.             SetGadgetAttrs(FSGadgets[GDX_FSALVGadget], FSwin, NULL,
  1214.                 ALV_LeftPixelOffset, ULONG_MAX,
  1215.                 TAG_END);
  1216.             }
  1217.         else
  1218.             {
  1219.             SetGadgetAttrs(FSGadgets[GDX_FSALVGadget], FSwin, NULL,
  1220.                 ALV_ScrollRight, 1,
  1221.                 TAG_END);
  1222.             }
  1223.         }
  1224. }
  1225.  
  1226.  
  1227. static BOOL HandleStrGadCode(USHORT code)
  1228. {
  1229.     BOOL Result = FALSE;
  1230.  
  1231.     switch (code)
  1232.         {
  1233.     case GADCODE_HELP:
  1234.         ToggleHelp();
  1235.         break;
  1236.     case GADCODE_UP:
  1237.         ScrollFSWindow(GADCODE_UP, 0);
  1238.         break;
  1239.     case GADCODE_PAGEUP:
  1240.         ScrollFSWindow(GADCODE_UP, IEQUALIFIER_LSHIFT);
  1241.         break;
  1242.     case GADCODE_TOP:
  1243.         ScrollFSWindow(GADCODE_UP, IEQUALIFIER_CONTROL);
  1244.         break;
  1245.     case GADCODE_DOWN:
  1246.         ScrollFSWindow(GADCODE_DOWN, 0);
  1247.         break;
  1248.     case GADCODE_PAGEDOWN:
  1249.         ScrollFSWindow(GADCODE_DOWN, IEQUALIFIER_LSHIFT);
  1250.         break;
  1251.     case GADCODE_BOTTOM:
  1252.         ScrollFSWindow(GADCODE_DOWN, IEQUALIFIER_CONTROL);
  1253.         break;
  1254.     case 0:
  1255.         Result = TRUE;
  1256.         break;
  1257.         }
  1258.  
  1259.     return Result;
  1260. }
  1261.  
  1262.  
  1263. void SizeFSWindow(enum WindowSizeChg NewSize)
  1264. {
  1265.     static short LastWidth = 0;
  1266.     static short LastHeight = 0;
  1267.  
  1268.     ASSERT_VALID(FSwin);
  1269.  
  1270.     FSWindowPos.Left = FSwin->LeftEdge;
  1271.     FSWindowPos.Top = FSwin->TopEdge;
  1272.     FSWindowPos.Width = FSwin->Width - FSwin->BorderLeft - FSwin->BorderRight;
  1273.     FSWindowPos.Height = FSwin->Height - FSwin->BorderTop - FSwin->BorderBottom;
  1274.  
  1275.     InnerHeight = FSwin->Height - FSwin->BorderTop - FSwin->BorderBottom;
  1276.     InnerWidth = FSwin->Width - FSwin->BorderLeft - FSwin->BorderRight;
  1277.  
  1278.     switch (NewSize)
  1279.         {
  1280.     case WSC_SizeAdjusted:
  1281.         EraseRect(FSwin->RPort, FSwin->BorderLeft, FSwin->BorderTop,
  1282.             FSwin->Width - FSwin->BorderRight - 1,
  1283.             FSwin->Height - FSwin->BorderBottom - 1);
  1284.  
  1285.         InitFS();        // Gadgets neu erzeugen
  1286.  
  1287.         FSRender();
  1288.         break;
  1289.  
  1290.     case WSC_SizeChanged:
  1291.         if (FSwin->Height != LastHeight || FSwin->Width != LastWidth)
  1292.             {
  1293.             if (LastWidth > FSwin->BorderLeft && LastHeight > FSwin->BorderTop)
  1294.                 {
  1295.                 EraseRect(FSwin->RPort, FSwin->BorderLeft, FSwin->BorderTop,
  1296.                     min(FSwin->Width, LastWidth) - FSwin->BorderRight - 1,
  1297.                     min(FSwin->Height, LastHeight) - FSwin->BorderBottom - 1);
  1298.                 }
  1299.  
  1300.             InitFS();        // Gadgets neu erzeugen
  1301.  
  1302.             FSRender();
  1303.             }
  1304.         break;
  1305.         }
  1306.  
  1307.     LastHeight = FSwin->Height;
  1308.     LastWidth = FSwin->Width;
  1309. }
  1310.  
  1311.  
  1312. static char *NormalizeName(const char *Name)
  1313. {
  1314.     BPTR __aligned DirLock;
  1315.     char *NormalizedName;
  1316.  
  1317.     ASSERT_VALID(Name);
  1318.  
  1319.     if (*Name == '\0')    // "" -> "", nichts normalisieren
  1320.         return strdup(Name);
  1321.  
  1322.     DirLock = Lock((STRPTR) Name, ACCESS_READ);
  1323.     if (DirLock == NULL)
  1324.         {
  1325.         alarm(GetString(MSG_FS_CANNOTLOCK), (STRPTR) Name, GetIoErrText());
  1326.         return NULL;
  1327.         }
  1328.  
  1329.     NormalizedName = GetFullPathName(DirLock);
  1330.     UnLock(DirLock);
  1331.  
  1332.     return NormalizedName;
  1333. }
  1334.  
  1335.  
  1336. static struct FSDir *GetFSDir(const char *DirName, struct FSDirEntry *Parent)
  1337. {
  1338.     struct FSDir *dir;
  1339.     char *NormalizedName;
  1340.  
  1341.     ASSERT_VALID(DirName);
  1342.     ASSERT_VALID0(Parent);
  1343.  
  1344.     DirName = NormalizedName = NormalizeName(DirName);
  1345.     if (NULL == NormalizedName)
  1346.         return NULL;
  1347.  
  1348.     dir = SearchFSDir(DirName);    // Directory bereits angelegt ?
  1349.     if (dir)
  1350.         {
  1351.         if (dir->fsd_isComplete)
  1352.             {
  1353.             aktFSDir = dir;
  1354.             GT_SetGadgetAttrs(FSGadgets[GDX_FSDrawerGadget], FSwin, NULL,
  1355.                 GTST_String, aktFSDir->fsd_Name,
  1356.                 TAG_END);
  1357.             DisplayFSList(dir);
  1358.             }
  1359.         else
  1360.             {
  1361.             dir = aktFSDir = ReadFSDir(DirName, dir, Parent);
  1362.             }
  1363.         }
  1364.     else
  1365.         {
  1366.         // Directory neu lesen
  1367.         dir = aktFSDir = ReadFSDir(DirName, NULL, Parent);
  1368.         }
  1369.  
  1370.     free(NormalizedName);
  1371.  
  1372.     return dir;
  1373. }
  1374.  
  1375.  
  1376. static struct FSDir *ReadFSDir(const char *DirName, struct FSDir *Dir, struct FSDirEntry *Parent)
  1377. {
  1378.     char *NormalizedName;
  1379.     struct FSDir *LastDir;
  1380.     struct FSDirEntry *FSe, *FSold;
  1381.     short abortFSRead;
  1382.     unsigned long index, MinIndex, Step;
  1383.     struct FSDir *ParentDir;
  1384.     enum SelectType ParentSelected = ST_None;
  1385.     struct MinList NewEntryList;
  1386.     struct NextFileInfo nfInfo;
  1387.  
  1388.     ASSERT_VALID(DirName);
  1389.     ASSERT_VALID0(Dir);
  1390.     ASSERT_VALID0(Parent);
  1391.  
  1392.     if (!BeginDir(DirName, &nfInfo))
  1393.         {
  1394.         EndDir(&nfInfo);
  1395.         return NULL;
  1396.         }
  1397.  
  1398.     GT_SetGadgetAttrs(FSGadgets[GDX_FSRereadGadget], FSwin, NULL,
  1399.         GA_Disabled, TRUE,
  1400.         TAG_END);
  1401.  
  1402.     NewList((struct List *) &NewEntryList);
  1403.  
  1404.     DirName = NormalizedName = GetFullPathName(nfInfo.nfi_DirLock);
  1405.  
  1406.     if (Dir && ST_None != Dir->fsd_ParentSelected)
  1407.         ParentSelected = ST_Selected;
  1408.  
  1409.     // Suchen nach einem bereits ausgewählten Parent Directory
  1410.     index = 0l;
  1411.     do    {
  1412.         ParentDir = LookUpParentDir(DirName, &index);
  1413.  
  1414.         if (ParentDir && ParentDir->fsd_ParentSelected == ST_Selected)
  1415.             ParentSelected = ST_Selected;
  1416.         } while (ParentDir && !ParentSelected);
  1417.  
  1418.     if (Parent && ST_Selected == Parent->fse_Selected)
  1419.         ParentSelected = ST_Selected;
  1420.  
  1421.     LastDir = Dir;
  1422.  
  1423.     // Dir immer NEU anlegen
  1424.     Dir = MakeFSDir(DirName, NULL);
  1425.  
  1426.     free(NormalizedName);
  1427.  
  1428.     GT_SetGadgetAttrs(FSGadgets[GDX_FSDrawerGadget], FSwin, NULL,
  1429.         GTST_String, Dir->fsd_Name,
  1430.         TAG_END);
  1431.  
  1432.     SetGadgetAttrs(FSGadgets[GDX_FSALVGadget], FSwin, NULL,
  1433.         ALV_Records, (Dir && Dir->fsd_DirCount) ? Dir->fsd_EntryList[0] : NULL,
  1434.         TAG_END);
  1435.  
  1436.     FSGadgetShortHook.h_Data = &abortFSRead;
  1437.     aktFSDir = Dir;
  1438.     abortFSRead = FALSE;
  1439.  
  1440.     Dir->fsd_isComplete = FALSE;
  1441.  
  1442.     MinIndex = LONG_MAX;
  1443.     Step = 0;
  1444.     do    {
  1445.         size_t NewIndex;
  1446.  
  1447.         FSe = NextFSDirEntry(&nfInfo);
  1448.         if (FSe)
  1449.             {
  1450.             int FSResult;
  1451.             struct FSNewEntry *NewEntry;
  1452. #if 0
  1453.             char *FileName;
  1454.  
  1455.             FileName = ConcatDirName(Dir->fsd_Name, FSe->fse_Name);
  1456.             if (FileName)
  1457.                 {
  1458.                 FSe->fse_Icon = GetDiskObjectNew(FileName);
  1459.                 free(FileName);
  1460.                 }
  1461. #endif
  1462.             // Select von Parent übernehmen
  1463.             if ((ParentSelected != ST_None) && FSFileMatch(BackupOpt, FSe))
  1464.                 {
  1465.                 InternalSelectEntry(Dir, FSe,
  1466.                     ParentSelected == ST_Selected, FALSE, 1, TRUE);
  1467.                 }
  1468.  
  1469.             if (!isFile(FSe))
  1470.                 FSe->fse_HasSelects = LookUpFSDir(Dir->fsd_Name, FSe->fse_Name);
  1471.  
  1472.             FSold = LastDir ? FindFSEntry(FSe->fse_Name, LastDir) : NULL;
  1473.  
  1474.             NewIndex = InsertFSe(Dir, FSe);
  1475.  
  1476.             if (FSold && (ST_Selected == FSold->fse_Selected))
  1477.                 SelectDirEntry(Dir, NewIndex, FALSE);
  1478.  
  1479.             NewEntry = malloc(sizeof(struct FSNewEntry));
  1480.             if (NewEntry)
  1481.                 {
  1482.                 struct FSNewEntry *LastEntry;
  1483.  
  1484.                 NewEntry->fsn_Insert.ari_InsertAfter = (NewIndex > 0) ? 
  1485.                         &Dir->fsd_EntryList[NewIndex - 1]->fse_fsRecord: NULL;
  1486.                 NewEntry->fsn_Insert.ari_NewRecords = &FSe->fse_fsRecord;
  1487.                 NewEntry->fsn_Insert.ari_MoreInsert = NULL;
  1488.  
  1489.                 LastEntry = (struct FSNewEntry *) RemTail((struct List *) &NewEntryList);
  1490.                 if (LastEntry)
  1491.                     {
  1492.                     LastEntry->fsn_Insert.ari_MoreInsert = &NewEntry->fsn_Insert;
  1493.                     AddTail((struct List *) &NewEntryList, &LastEntry->fsn_Node);
  1494.                     }
  1495.                 AddTail((struct List *) &NewEntryList, &NewEntry->fsn_Node);
  1496.                 }
  1497.  
  1498.             MinIndex = min(NewIndex, MinIndex);
  1499.  
  1500.             if (Step >= FSDIR_STEP)
  1501.                 {
  1502.  
  1503.                 Step = 0;
  1504.                 MinIndex = LONG_MAX;
  1505.  
  1506.                 InsertEntryList((struct List *) &NewEntryList, FALSE);
  1507.                 }
  1508.  
  1509.             DuplicateOldEntry(Dir, LastDir, FSe);
  1510.  
  1511.             // Während des Lesens des Directories auf Eingaben reagieren...
  1512.             FSResult = chkinput();
  1513.             if (globalFSResult && FSResult)
  1514.                 {
  1515.                 *globalFSResult = FSResult;
  1516.                 if (FS_ABORT == FSResult || FS_START == FSResult)
  1517.                     GlobalFSStartCode = FSResult;
  1518.                 }
  1519.  
  1520.             Step++;
  1521.             }
  1522.  
  1523.         // <ParentSelected> mitführen falls <Dir> zwischenzeitlich ausgewählt wurde
  1524.         if (ST_None != Dir->fsd_ParentSelected)
  1525.             ParentSelected = ST_Selected;
  1526.         } while (!abortFSRead && FSe && FSwin);
  1527.  
  1528.     InsertEntryList((struct List *) &NewEntryList, abortFSRead);
  1529.  
  1530.     if (!abortFSRead)
  1531.         {
  1532.         // Länge der Liste auf <DirCount+2> begrenzen, um keinen unnötigen Speicherplatz zu belegen
  1533.         SetFSDirListSize(Dir, Dir->fsd_DirCount + 2);
  1534.  
  1535.         Dir->fsd_isComplete = TRUE;
  1536.         }
  1537.  
  1538.     if (LastDir)
  1539.         {
  1540.         struct FSDirEntry **vList;
  1541.         unsigned short vCount;
  1542.  
  1543.         // Einträge in LastDir und Dir vertauschen. Die alten Einträge aus Dir
  1544.         // werden dann zusammen mit LastDir vernichtet.
  1545.  
  1546.         vCount = LastDir->fsd_DirCount;
  1547.         LastDir->fsd_DirCount = Dir->fsd_DirCount;
  1548.         Dir->fsd_DirCount = vCount;
  1549.  
  1550.         vList = LastDir->fsd_EntryList;
  1551.         LastDir->fsd_EntryList = Dir->fsd_EntryList;
  1552.         Dir->fsd_EntryList = vList;
  1553.  
  1554.         LastDir->fsd_isComplete = Dir->fsd_isComplete;
  1555.  
  1556.         RemoveFSDir(Dir);
  1557.         aktFSDir = LastDir;
  1558.         }
  1559.  
  1560.     FSGadgetShortHook.h_Data = NULL;
  1561.     EndDir(&nfInfo);
  1562.  
  1563.     GT_SetGadgetAttrs(FSGadgets[GDX_FSRereadGadget], FSwin, NULL,
  1564.         GA_Disabled, FALSE,
  1565.         TAG_END);
  1566.  
  1567.     return aktFSDir;
  1568. }
  1569.  
  1570.  
  1571. static void InsertEntryList(struct List *EntryList, BOOL ClearOnly)
  1572. {
  1573.     struct FSNewEntry *OldEntry;
  1574.  
  1575.     OldEntry = (struct FSNewEntry *) RemHead(EntryList);
  1576.     if (OldEntry && !ClearOnly)
  1577.         {
  1578.         SetGadgetAttrs(FSGadgets[GDX_FSALVGadget], FSwin, NULL,
  1579.             ALV_InsertRecords, &OldEntry->fsn_Insert,
  1580.             TAG_END);
  1581.         }
  1582.  
  1583.     // NewEntryList wieder leeren
  1584.     while (OldEntry)
  1585.         {
  1586.         free(OldEntry);
  1587.  
  1588.         OldEntry = (struct FSNewEntry *) RemHead(EntryList);
  1589.         }
  1590. }
  1591.  
  1592.  
  1593. static short BeginDir(const char *DirName, struct NextFileInfo *nfInfo)
  1594. {
  1595.     ASSERT_VALID(DirName);
  1596.     ASSERT_VALID(nfInfo);
  1597.  
  1598.     nfInfo->nfi_eaControl = AllocDosObject(DOS_EXALLCONTROL, NULL);
  1599.     if (NULL == nfInfo->nfi_eaControl)
  1600.         return NULL;
  1601.  
  1602.     nfInfo->nfi_eaBuffer = malloc(EXALL_BUFFSIZE); 
  1603.     if (NULL == nfInfo->nfi_eaBuffer)
  1604.         return NULL;
  1605.  
  1606.     nfInfo->nfi_DirLock = Lock((STRPTR) DirName, ACCESS_READ);
  1607.     if (nfInfo->nfi_DirLock == NULL)
  1608.         return FALSE;
  1609.  
  1610.     // !!!!! lebenswichtige Initialisierung für ExAll() !!!!!
  1611.     nfInfo->nfi_eaControl->eac_LastKey = 0;
  1612.  
  1613.     ExAllNFInfo(nfInfo, ED_DATE);
  1614.  
  1615.     return TRUE;
  1616. }
  1617.  
  1618.  
  1619. static void EndDir(struct NextFileInfo *nfInfo)
  1620. {
  1621.     ASSERT_VALID(nfInfo);
  1622.  
  1623.     if (nfInfo->nfi_eaControl && nfInfo->nfi_eaBuffer && nfInfo->nfi_eaMore)
  1624.         {
  1625.         // ExAll() war noch nicht fertig
  1626.         ExAllEnd(nfInfo->nfi_DirLock, nfInfo->nfi_eaBuffer, 
  1627.                 EXALL_BUFFSIZE, ED_DATE, nfInfo->nfi_eaControl);
  1628.         }
  1629.     if (nfInfo->nfi_eaControl)
  1630.         {
  1631.         FreeDosObject(DOS_EXALLCONTROL, nfInfo->nfi_eaControl);
  1632.         nfInfo->nfi_eaControl = NULL;
  1633.         }
  1634.     if (nfInfo->nfi_eaBuffer)
  1635.         {
  1636.         free(nfInfo->nfi_eaBuffer);
  1637.         nfInfo->nfi_eaBuffer = NULL;
  1638.         }
  1639.     if (nfInfo->nfi_DirLock)
  1640.         {
  1641.         UnLock(nfInfo->nfi_DirLock);
  1642.         nfInfo->nfi_DirLock = NULL;
  1643.         }
  1644. }
  1645.  
  1646.  
  1647. static struct FSDirEntry *NextFSDirEntry(struct NextFileInfo *nfInfo)
  1648. {
  1649.     struct FSDirEntry *result = NULL;
  1650.  
  1651.     ASSERT_VALID(nfInfo);
  1652.  
  1653.     while (NULL == nfInfo->nfi_eaData && nfInfo->nfi_eaMore)
  1654.         {
  1655.         ExAllNFInfo(nfInfo, ED_DATE);
  1656.         }
  1657.  
  1658.     if (nfInfo->nfi_eaData)
  1659.         {
  1660.         result = NewFSEntry(nfInfo->nfi_eaData->ed_Name,
  1661.                 GetFibType(nfInfo->nfi_eaData->ed_Type, nfInfo->nfi_eaData->ed_Name, nfInfo->nfi_DirLock));
  1662.  
  1663.         if (result)
  1664.             {
  1665.             result->fse_Protection = nfInfo->nfi_eaData->ed_Prot;
  1666.             result->fse_Size = nfInfo->nfi_eaData->ed_Size;
  1667.  
  1668.             result->fse_Date.ds_Days = nfInfo->nfi_eaData->ed_Days;
  1669.             result->fse_Date.ds_Minute = nfInfo->nfi_eaData->ed_Mins;
  1670.             result->fse_Date.ds_Tick = nfInfo->nfi_eaData->ed_Ticks;
  1671.             }
  1672.  
  1673.         nfInfo->nfi_eaData = nfInfo->nfi_eaData->ed_Next;
  1674.         }
  1675.  
  1676.     return result;
  1677. }
  1678.  
  1679.  
  1680. static enum FType GetFibType(long EntryType, const STRPTR Name, BPTR DirLock)
  1681. {
  1682.     enum FType result;
  1683.  
  1684.     ASSERT_VALID(Name);
  1685.     ASSERT_VALID(BADDR(DirLock));
  1686.  
  1687.     switch (EntryType)
  1688.         {
  1689.     case ST_SOFTLINK:
  1690.         result = SoftLinkType(Name, DirLock);
  1691.         break;
  1692.     case ST_LINKFILE:
  1693.         result = HardLinkFile;
  1694.         break;
  1695.     case ST_LINKDIR:
  1696.         result = HardLinkDir;
  1697.         break;
  1698.     default:
  1699.         result = (EntryType < 0) ? File : Directory;
  1700.         }
  1701.  
  1702.     return result;
  1703. }
  1704.  
  1705.  
  1706. struct FSDirEntry *AddFSEntry(struct FSDir *Dir, const char *Name, enum FType Typ)
  1707. {
  1708.     struct FSDirEntry *FSe;
  1709.  
  1710.     ASSERT_VALID(Dir);
  1711.     ASSERT_VALID(Name);
  1712.  
  1713.     FSe = FindFSEntry(Name, Dir);
  1714.     if (!FSe)
  1715.         {
  1716.         FSe = NewFSEntry(Name, Typ);
  1717.  
  1718.         if (Dir->fsd_DirCount > 0)
  1719.             Dir->fsd_EntryList[Dir->fsd_DirCount - 1]->fse_fsRecord.alr_NextRecord = FSe;
  1720.         FSe->fse_fsRecord.alr_NextRecord = NULL;
  1721.  
  1722.         Dir->fsd_EntryList[Dir->fsd_DirCount] = FSe;
  1723.         Dir->fsd_DirCount++;
  1724.         }
  1725.  
  1726.     return FSe;
  1727. }
  1728.  
  1729.  
  1730. static struct FSDirEntry *NewFSEntry(const char *Name, enum FType Typ)
  1731. {
  1732.     unsigned short l;
  1733.     char c;
  1734.     struct FSDirEntry *FSe;
  1735.  
  1736.     ASSERT_VALID(Name);
  1737.  
  1738.     l = strlen(Name);
  1739.     c = Name[l-1];
  1740.     if (':' != c && (Typ == Volume || Typ == Assign || Typ == Device))
  1741.         l++;            // Platz lassen für ':'
  1742.  
  1743.     FSe = (struct FSDirEntry *) malloc(sizeof(struct FSDirEntry) + l);
  1744.     if (FSe == NULL)
  1745.         {
  1746.         alarm(GetString(MSG_OUTOFMEMORY), __FUNC__, "FSe", sizeof(struct FSDirEntry) + l);
  1747.         myabort(10);
  1748.         }
  1749.     FSe->fse_Contents = NULL;
  1750.     FSe->fse_HasSelects = FALSE;
  1751.     FSe->fse_Selected = ST_None;
  1752.     FSe->fse_ManualSelect = ST_None;
  1753.     FSe->fse_Typ = Typ;
  1754.     FSe->fse_NameLength = l;
  1755.     FSe->fse_Icon = NULL;
  1756.  
  1757.     FSe->fse_fsRecord.alr_RecordData = FSe;
  1758.     FSe->fse_fsRecord.alr_Flags = 0l;
  1759.     FSe->fse_fsRecord.alr_Font.afd_FontAttr = NULL;
  1760.     FSe->fse_fsRecord.alr_Font.afd_SoftStyleStyle = FS_NORMAL;
  1761.     FSe->fse_fsRecord.alr_Font.afd_SoftStyleEnable = FS_NORMAL;
  1762.     FSe->fse_fsRecord.alr_NextRecord = NULL;
  1763.     FSe->fse_fsRecord.alr_Private = NULL;
  1764.  
  1765.     strcpy(FSe->fse_Name, Name);
  1766.     if (':' != c && (Typ == Volume || Typ == Assign || Typ == Device))
  1767.         strcat(FSe->fse_Name, ":");
  1768.  
  1769.     // Hilite-Markierung für Directories setzen
  1770.     if (!isFile(FSe))
  1771.         FSe->fse_fsRecord.alr_Flags |= ALRF_HILITE;
  1772.  
  1773.     switch (Typ)
  1774.         {
  1775.     case SoftLinkDir:
  1776.     case Directory:
  1777.     case HardLinkDir:
  1778.     case EmptyDir:
  1779.         FSe->fse_Image = &DrawerImage;
  1780.         break;
  1781.     case Assign:
  1782.         FSe->fse_fsRecord.alr_Flags |= ALRF_HILITE;        // Hilite-Markierung für Assigns setzen
  1783.         FSe->fse_Image = &AssignImage;
  1784.         break;
  1785.     case Volume:
  1786.         FSe->fse_Image = &VolumeImage;
  1787.         break;
  1788.     default:
  1789.         FSe->fse_Image = NULL;
  1790.         break;
  1791.         }
  1792.  
  1793.     return FSe;
  1794. }
  1795.  
  1796.  
  1797. static void DestroyFSEntry(struct FSDirEntry **FSe)
  1798. {
  1799.     if ((*FSe)->fse_Icon)
  1800.         {
  1801.         FreeDiskObject((*FSe)->fse_Icon);
  1802.         (*FSe)->fse_Icon = NULL;
  1803.         }
  1804.     free(*FSe);
  1805.     *FSe = NULL;
  1806. }
  1807.  
  1808.  
  1809. struct FSDir *CreateFSDir(const char *DirName, struct BackupOptions *Options)
  1810. {
  1811.     struct FSDir *Parent, *Dir;
  1812.     char *NormalizedName = NULL;
  1813.  
  1814.     ASSERT_VALID(DirName);
  1815.  
  1816.     if (*DirName)
  1817.         {
  1818.         // nicht bei Volume-Listen!
  1819.         DirName = NormalizedName = NormalizeName(DirName);
  1820.         if (DirName == NULL)
  1821.             return NULL;
  1822.         }
  1823.  
  1824.     Dir = SearchFSDir(DirName);
  1825.     if (!Dir)
  1826.         Dir = MakeFSDir(DirName, Options);
  1827.  
  1828.     if (Parent = SearchFSDir(FindParentName((STRPTR) DirName)))
  1829.     Dir->fsd_ParentEntry = FindFSEntry(NurName(DirName), Parent);
  1830.  
  1831.     if (NormalizedName)
  1832.         free(NormalizedName);
  1833.  
  1834.     return Dir;
  1835. }
  1836.  
  1837.  
  1838. static struct FSDir *MakeFSDir(const char *DirName, struct BackupOptions *Options)
  1839. {
  1840.     struct FSDir *dir;
  1841.  
  1842.     ASSERT_VALID(DirName);
  1843.  
  1844.     dir = calloc(sizeof(struct FSDir), 1);
  1845.     if (dir == NULL)
  1846.         {
  1847.         alarm(GetString(MSG_OUTOFMEMORY), __FUNC__, "dir", sizeof(struct FSDir));
  1848.         myabort(10);
  1849.         }
  1850.  
  1851.     dir->fsd_Name = strdup(DirName);
  1852.     if (dir->fsd_Name == NULL)
  1853.         {
  1854.         alarm(GetString(MSG_OUTOFMEMORY), __FUNC__, "Name", strlen(DirName));
  1855.         myabort(10);
  1856.         }
  1857.  
  1858.     dir->fsd_ParentEntry = NULL;
  1859.     dir->fsd_DirCount = 0;
  1860.     dir->fsd_SelectCount = 0;
  1861.     dir->fsd_isComplete = FALSE;
  1862.     dir->fsd_ParentSelected = FALSE;
  1863.     dir->fsd_HasSelects = FALSE;
  1864.     dir->fsd_isVolList = FALSE;
  1865.     dir->fsd_ListSize = DEFAULTLISTSIZE;
  1866.     dir->fsd_DirOptions = Options;
  1867.     dir->fsd_TopLine = 0l;
  1868.  
  1869.     dir->fsd_EntryList = (struct FSDirEntry **) calloc(dir->fsd_ListSize, sizeof(struct FSDirEntry *));
  1870.     if (dir->fsd_EntryList == NULL)
  1871.         {
  1872.         alarm(GetString(MSG_OUTOFMEMORY), __FUNC__, "DirList[1]", dir->fsd_ListSize * sizeof(struct FSDirEntry *));
  1873.         myabort(10);
  1874.         }
  1875.  
  1876.     if (BackupOpt->bo_FSDirCount >= MainFSDirLength)
  1877.         {
  1878.         // BackupOpt->bo_FSDirList verlängern
  1879.         MainFSDirLength += DEFAULTLISTSIZE;
  1880.         if (BackupOpt->bo_FSDirList)
  1881.             {
  1882.             BackupOpt->bo_FSDirList = realloc(BackupOpt->bo_FSDirList,
  1883.                 MainFSDirLength * sizeof(struct FSDir *));
  1884.             }
  1885.         else
  1886.             {
  1887.             BackupOpt->bo_FSDirList = calloc(MainFSDirLength,
  1888.                 sizeof(struct FSDir *));
  1889.             }
  1890.  
  1891.         if (BackupOpt->bo_FSDirList == NULL)
  1892.             {
  1893.             alarm(GetString(MSG_OUTOFMEMORY), __FUNC__, "DirList[2]", MainFSDirLength * sizeof(struct FSDir *));
  1894.             myabort(10);
  1895.             }
  1896.         }
  1897.  
  1898.     // neues Directory eintragen
  1899.     BackupOpt->bo_FSDirList[BackupOpt->bo_FSDirCount++] = dir;
  1900.  
  1901.     return dir;
  1902. }
  1903.  
  1904.  
  1905. // Eintrag <Dir> aus BackupOpt->bo_FSDirList entfernen und auflösen
  1906. static void RemoveFSDir(struct FSDir *Dir)
  1907. {
  1908.     unsigned long n;
  1909.     short found;
  1910.     unsigned short m;
  1911.  
  1912.     ASSERT_VALID(Dir);
  1913.  
  1914.     for (found=0, n=0; !found && n<BackupOpt->bo_FSDirCount; n++)
  1915.         {
  1916.         found = BackupOpt->bo_FSDirList[n] == Dir;
  1917.         if (found)
  1918.             {
  1919.             // SelectCount für Dirs und Files korrigieren
  1920.             for (m=0; m<Dir->fsd_DirCount; m++)
  1921.                 {
  1922.                 if (ST_Selected == Dir->fsd_EntryList[m]->fse_Selected)
  1923.                     {
  1924.                     if (isFile(Dir->fsd_EntryList[m]))
  1925.                         FSFileSelectCount--;
  1926.                     else
  1927.                         FSDirSelectCount--;
  1928.                     }
  1929.                 }
  1930.             // Dir aus der Liste streichen
  1931.             while (n < BackupOpt->bo_FSDirCount-1)
  1932.                 {
  1933.                 BackupOpt->bo_FSDirList[n] = BackupOpt->bo_FSDirList[n+1];
  1934.                 n++;
  1935.                 }
  1936.             }
  1937.         }
  1938.  
  1939.     EmptyFSDir(Dir);
  1940.     free(Dir);
  1941.  
  1942.     BackupOpt->bo_FSDirCount--;
  1943. }
  1944.  
  1945.  
  1946. // EntryList um DEFAULTLISTSIZE verlängern
  1947. static void ExtendFSDir(struct FSDir *dir)
  1948. {
  1949.     ASSERT_VALID(dir);
  1950.     SetFSDirListSize(dir, dir->fsd_ListSize + DEFAULTLISTSIZE);
  1951. }
  1952.  
  1953.  
  1954. // EntryList auf <NewSize> einstellen
  1955. static void SetFSDirListSize(struct FSDir *dir, unsigned long NewSize)
  1956. {
  1957.     ASSERT_VALID(dir);
  1958.     dir->fsd_ListSize = NewSize;
  1959.  
  1960.     dir->fsd_EntryList = realloc(dir->fsd_EntryList, NewSize * sizeof(struct FSDirEntry *));
  1961.     if (dir->fsd_EntryList == NULL)
  1962.         {
  1963.         alarm(GetString(MSG_OUTOFMEMORY), __FUNC__, "EntryList", NewSize * sizeof(struct FSDirEntry *));
  1964.         myabort(10);
  1965.         }
  1966. }
  1967.  
  1968.  
  1969. // <FSe> in <Dir> finden und Anzeige aktualisieren
  1970. static void FindAndRedisplayDirEntry(struct FSDir *Dir, struct FSDirEntry *FSe,
  1971.     ULONG FirstColumn, ULONG LastColumn, enum RedisplayMode Changed)
  1972. {
  1973.     ULONG RecNo;
  1974.  
  1975.     ASSERT_VALID(Dir);
  1976.     ASSERT_VALID(FSe);
  1977.  
  1978.     if (aktFSDir != Dir)
  1979.         return;        // keine Anzeige wenn dies nicht das aktuelle Directory ist!
  1980.  
  1981.     // RecordNummer von <FSe> in <Dir> finden
  1982.     for (RecNo=0; RecNo<Dir->fsd_DirCount; RecNo++)
  1983.         {
  1984.         if (Dir->fsd_EntryList[RecNo] == FSe)
  1985.             {
  1986.             struct ALVRecordChange rChg;
  1987.  
  1988.             rChg.arc_FirstRecord = &FSe->fse_fsRecord;
  1989.             rChg.arc_RecordCount = 1;
  1990.             rChg.arc_FirstColumnNo = FirstColumn;
  1991.             rChg.arc_LastColumnNo = LastColumn;
  1992.             rChg.arc_ContentsChanged = RDM_ContentsChanged == Changed;
  1993.  
  1994.             SetGadgetAttrs(FSGadgets[GDX_FSALVGadget], FSwin, NULL,
  1995.                 ALV_InvalidateRecords, &rChg,
  1996.                 TAG_END);
  1997.  
  1998.             break;
  1999.             }
  2000.         }
  2001.  
  2002. }
  2003.  
  2004.  
  2005. static void DisplayFSList(struct FSDir *Dir)
  2006. {
  2007.     SetGadgetAttrs(FSGadgets[GDX_FSALVGadget], FSwin, NULL,
  2008.         ALV_Records, (Dir && Dir->fsd_DirCount) ? Dir->fsd_EntryList[0] : NULL,
  2009.         TAG_END);
  2010. }
  2011.  
  2012.  
  2013. void SortAllFSDirs(void)
  2014. {
  2015.     size_t n;
  2016.  
  2017.     for (n=0; n<BackupOpt->bo_FSDirCount; n++)
  2018.         {
  2019.         SortFSList(BackupOpt->bo_FSDirList[n]);
  2020.         }
  2021. }
  2022.  
  2023.  
  2024. static void SortFSList(struct FSDir *dir)
  2025. {
  2026.     size_t n;
  2027.  
  2028.     ASSERT_VALID(dir);
  2029.  
  2030.     qsort((char *) dir->fsd_EntryList, dir->fsd_DirCount,
  2031.         sizeof(struct FSDirEntry *), BackupOpt->bo_FSCompare);
  2032.  
  2033.     // ALVRecords richtig verketten
  2034.     for (n=0; n<dir->fsd_DirCount; n++)
  2035.         {
  2036.         if (n < dir->fsd_DirCount - 1)
  2037.             dir->fsd_EntryList[n]->fse_fsRecord.alr_NextRecord = dir->fsd_EntryList[n + 1];
  2038.         else
  2039.             dir->fsd_EntryList[n]->fse_fsRecord.alr_NextRecord = NULL;
  2040.         }
  2041.  
  2042.     // frisch sortierte Liste anzeigen
  2043.     if (dir == aktFSDir)
  2044.         DisplayFSList(dir);
  2045. }
  2046.  
  2047.  
  2048. int FSCompareName(struct FSDirEntry **fs1, struct FSDirEntry **fs2)
  2049. {
  2050.     ASSERT_VALID(*fs1);
  2051.     ASSERT_VALID(*fs2);
  2052.  
  2053.     if (DifferentType(*fs1, *fs2))
  2054.         {
  2055.         switch (BackupOpt->bo_WhereSortDirs)
  2056.             {
  2057.         case DirFirst:
  2058.             return (*fs2)->fse_Typ - (*fs1)->fse_Typ;
  2059.             break;
  2060.         case DirLast:
  2061.             return (*fs1)->fse_Typ - (*fs2)->fse_Typ;
  2062.             break;
  2063.         case DirBetween:
  2064.             break;
  2065.             }
  2066.         }
  2067.  
  2068.     return stricmp((*fs1)->fse_Name, (*fs2)->fse_Name);
  2069. }
  2070.  
  2071.  
  2072. // absteigend nach Datum & Uhrzeit sortieren
  2073. int FSCompareDate(struct FSDirEntry **fs1, struct FSDirEntry **fs2)
  2074. {
  2075.     ASSERT_VALID(*fs1);
  2076.     ASSERT_VALID(*fs2);
  2077.  
  2078.     if (DifferentType(*fs1, *fs2))
  2079.         {
  2080.         switch (BackupOpt->bo_WhereSortDirs)
  2081.             {
  2082.         case DirFirst:
  2083.             return (*fs2)->fse_Typ - (*fs1)->fse_Typ;
  2084.             break;
  2085.         case DirLast:
  2086.             return (*fs1)->fse_Typ - (*fs2)->fse_Typ;
  2087.             break;
  2088.         case DirBetween:
  2089.             break;
  2090.             }
  2091.         }
  2092.  
  2093.     if ((*fs1)->fse_Date.ds_Days != (*fs2)->fse_Date.ds_Days)
  2094.         return (*fs2)->fse_Date.ds_Days - (*fs1)->fse_Date.ds_Days;
  2095.  
  2096.     if ((*fs1)->fse_Date.ds_Minute != (*fs2)->fse_Date.ds_Minute)
  2097.         return (*fs2)->fse_Date.ds_Minute - (*fs1)->fse_Date.ds_Minute;
  2098.  
  2099.     return (*fs2)->fse_Date.ds_Tick - (*fs1)->fse_Date.ds_Tick;
  2100. }
  2101.  
  2102.  
  2103. // aufsteigend nach Größe sortieren
  2104. int FSCompareSize(struct FSDirEntry **fs1, struct FSDirEntry **fs2)
  2105. {
  2106.     ASSERT_VALID(*fs1);
  2107.     ASSERT_VALID(*fs2);
  2108.  
  2109.     if (DifferentType(*fs1, *fs2))
  2110.         {
  2111.         switch (BackupOpt->bo_WhereSortDirs)
  2112.             {
  2113.         case DirFirst:
  2114.         case DirBetween:
  2115.             return (*fs2)->fse_Typ - (*fs1)->fse_Typ;
  2116.             break;
  2117.         case DirLast:
  2118.             return (*fs1)->fse_Typ - (*fs2)->fse_Typ;
  2119.             break;
  2120.             }
  2121.         }
  2122.  
  2123.     return (int) ((*fs1)->fse_Size - (*fs2)->fse_Size);
  2124. }
  2125.  
  2126.  
  2127. static short DifferentType(const struct FSDirEntry *fs1, const struct FSDirEntry *fs2)
  2128. {
  2129.     ASSERT_VALID(fs1);
  2130.     ASSERT_VALID(fs2);
  2131.  
  2132.     return (short) ((fs1->fse_Typ != fs2->fse_Typ) && (!isFile(fs1) || !isFile(fs2)));
  2133. }
  2134.  
  2135.  
  2136. static void FSSubDir(struct FSDirEntry *SubDirEntry)
  2137. {
  2138.     char *NewDirName;
  2139.     struct FSDir *SubDir;
  2140.  
  2141.     if (isFile(SubDirEntry))
  2142.         return;
  2143.  
  2144.     SetFSHasSelects(aktFSDir);
  2145.  
  2146.     GetAttr(ALV_TopLine, FSGadgets[GDX_FSALVGadget], &aktFSDir->fsd_TopLine);    // TopLine merken
  2147.  
  2148.     NewDirName = ConcatDirName(aktFSDir->fsd_Name, SubDirEntry->fse_Name);
  2149.  
  2150.     SubDir = SubDirEntry->fse_Contents;
  2151.     if (SubDir == NULL)
  2152.         SubDir = SearchFSDir(NewDirName);
  2153.  
  2154.     if (SubDir)
  2155.         {
  2156.         if (SubDir->fsd_isComplete)
  2157.             {
  2158.             // Directory bereits vollständig gelesen
  2159.             aktFSDir = SubDir;
  2160.             ReSortEntryList(aktFSDir);
  2161.             GT_SetGadgetAttrs(FSGadgets[GDX_FSDrawerGadget], FSwin, NULL,
  2162.                 GTST_String, aktFSDir->fsd_Name,
  2163.                 TAG_END);
  2164.             }
  2165.         else
  2166.             {
  2167.             // Directory schon einmal teilweise gelesen
  2168.             aktFSDir = ReadFSDir(SubDir->fsd_Name, SubDir, SubDirEntry);
  2169.             }
  2170.         }
  2171.     else
  2172.         {
  2173.         // Directory noch nie gelesen
  2174.         SubDirEntry->fse_Contents = GetFSDir(NewDirName, SubDirEntry);
  2175.  
  2176.         aktFSDir->fsd_ParentEntry = SubDirEntry;
  2177.         }
  2178.  
  2179.     free(NewDirName);
  2180.  
  2181.     aktFSDir->fsd_ParentSelected = aktFSDir->fsd_ParentSelected ||
  2182.             ST_Selected == SubDirEntry->fse_Selected;
  2183.  
  2184.     GT_SetGadgetAttrs(FSGadgets[GDX_FSParentGadget], FSwin, NULL,
  2185.         GA_Disabled, aktFSDir->fsd_isVolList,
  2186.         TAG_END);
  2187. }
  2188.  
  2189.  
  2190. static void FSParentDir(void)
  2191. {
  2192.     struct FSDir *Child, *Parent;
  2193.     struct FSDirEntry *FSe;
  2194.     char *SubDirName;
  2195.  
  2196.     // Kein Parent bei der Volume-Liste
  2197.     if (aktFSDir->fsd_isVolList)
  2198.         return;
  2199.  
  2200.     SetFSHasSelects(aktFSDir);
  2201.  
  2202.     GetAttr(ALV_TopLine, FSGadgets[GDX_FSALVGadget], &aktFSDir->fsd_TopLine);
  2203.  
  2204.     Child = aktFSDir;
  2205.  
  2206.     if (aktFSDir->fsd_Name[strlen(aktFSDir->fsd_Name)-1] == ':')
  2207.         {
  2208.         // wir sind schon im Root Directory
  2209.         Parent = GetVolumes();
  2210.  
  2211.         GT_SetGadgetAttrs(FSGadgets[GDX_FSParentGadget], FSwin, NULL,
  2212.             GA_Disabled, TRUE,
  2213.             TAG_END);
  2214.         aktFSDir = Parent;
  2215.  
  2216.         SubDirName = Child->fsd_Name;
  2217.         DisplayFSList(aktFSDir);
  2218.         }
  2219.     else
  2220.         {
  2221.         Parent = aktFSDir =
  2222.             GetFSDir(FindParentName(Child->fsd_Name), NULL);
  2223.  
  2224.         SubDirName = Child->fsd_Name + strlen(Child->fsd_Name) - 1;
  2225.         while (SubDirName != Child->fsd_Name &&
  2226.                 *SubDirName != '/' && *SubDirName != ':')
  2227.             SubDirName--;
  2228.  
  2229.         SubDirName++;
  2230.         }
  2231.  
  2232.     FSe = FindFSEntry(SubDirName, Parent);
  2233.     if (FSe)
  2234.         {
  2235.         short OldHasSelects;
  2236.  
  2237.         Child->fsd_ParentEntry = FSe;
  2238.         FSe->fse_Contents = Child;
  2239.         OldHasSelects = FSe->fse_HasSelects;
  2240.         FSe->fse_HasSelects = Child->fsd_HasSelects || ManualSelectCount(Child) > 0;
  2241.  
  2242.         if (OldHasSelects != FSe->fse_HasSelects)
  2243.             FindAndRedisplayDirEntry(Parent, FSe, 0, 0, RDM_ContentsChanged);
  2244.         }
  2245.  
  2246.     GT_SetGadgetAttrs(FSGadgets[GDX_FSDrawerGadget], FSwin, NULL,
  2247.         GTST_String, aktFSDir->fsd_Name,
  2248.         TAG_END);
  2249.     SetGadgetAttrs(FSGadgets[GDX_FSALVGadget], FSwin, NULL,
  2250.         ALV_TopLine, aktFSDir ? aktFSDir->fsd_TopLine : 0l,
  2251.         TAG_END);
  2252. }
  2253.  
  2254.  
  2255. // sucht nach allen Volumes im System
  2256. static struct FSDir *GetVolumes(void)
  2257. {
  2258.     struct FSDir *Dir, *LastDir;
  2259.     struct FSDirEntry *FSe = NULL;
  2260.     struct DosList *dlist;
  2261.     struct Process *myProcess;
  2262.     char *bname;
  2263.  
  2264.     SetBusyPointer(FSwin, TRUE);
  2265.  
  2266.     SetFSHasSelects(aktFSDir);
  2267.  
  2268.     Dir = SearchFSDir("");
  2269.  
  2270.     LastDir = Dir;
  2271.  
  2272.     Dir = MakeFSDir("", NULL);        // Dir neu anlegen
  2273.     Dir->fsd_isVolList = TRUE;
  2274.  
  2275.     // keine Requester "Insert Volume XXX:" bei nicht gemounteten Volumes!
  2276.     myProcess = (struct Process *) FindTask(NULL);
  2277.     myProcess->pr_WindowPtr = (APTR) ~0;
  2278.  
  2279.     dlist = LockDosList(DOSLIST_FLAGS);
  2280.     dlist = NextDosEntry(dlist, DOSLIST_FLAGS);
  2281.     while (dlist)
  2282.         {
  2283.         BPTR DLLock;
  2284.  
  2285.         bname = btocstr(dlist->dol_Name);
  2286.  
  2287.         switch (dlist->dol_Type)
  2288.             {
  2289.         case DLT_DEVICE:
  2290.             if (dlist->dol_misc.dol_handler.dol_Startup)
  2291.                 {
  2292.                 struct FileSysStartupMsg *Startup;
  2293.                 struct DosEnvec *env;
  2294.  
  2295.                 Startup = (struct FileSysStartupMsg *) BADDR(dlist->dol_misc.dol_handler.dol_Startup);
  2296.                 if (Startup != NULL && (TypeOfMem(Startup) != 0L ||inROM((APTR) Startup)))
  2297.                     env = (struct DosEnvec *) BADDR(Startup->fssm_Environ);
  2298.                 else
  2299.                     env = NULL;
  2300.  
  2301.                 if (env != NULL && (TypeOfMem(env) != 0L ||inROM((APTR) env)))
  2302.                     {
  2303.                     FSe = NewFSEntry(bname, Device);
  2304.                     FSe->fse_eInfo = env;
  2305.                     FSe->fse_Size = (1 + env->de_HighCyl - env->de_LowCyl)
  2306.                         * env->de_Surfaces * env->de_BlocksPerTrack
  2307.                         * (env->de_SizeBlock << 2);    // Größe in Bytes
  2308.  
  2309.                     }
  2310.                 else if (FSe)
  2311.                     {
  2312.                     DestroyFSEntry(&FSe);
  2313.                     }
  2314.                 }
  2315.             else
  2316.                 FSe = NULL;
  2317.             break;
  2318.  
  2319.         case DLT_VOLUME:
  2320.             FSe = NewFSEntry(bname, Volume);
  2321.             FSe->fse_Date = dlist->dol_misc.dol_volume.dol_VolumeDate;
  2322.             break;
  2323.  
  2324.         default:
  2325.             FSe = NewFSEntry(bname, Assign);
  2326.             break;
  2327.             }
  2328.  
  2329.         if (FSe)
  2330.             {
  2331.             if (dlist->dol_Type == DLT_DEVICE)
  2332.                 {
  2333.                 FSe->fse_HasSelects = 0;
  2334.  
  2335.                 if (Dir->fsd_DirCount >= Dir->fsd_ListSize)
  2336.                     ExtendFSDir(Dir);
  2337.  
  2338.                 Dir->fsd_EntryList[Dir->fsd_DirCount] = FSe;
  2339.                 ++Dir->fsd_DirCount;
  2340.  
  2341.                 DuplicateOldEntry(Dir, LastDir, FSe);
  2342.                 }
  2343.             else
  2344.                 {
  2345.                 DLLock = Lock(FSe->fse_Name, ACCESS_READ);
  2346.                 if (NULL == DLLock)
  2347.                     {
  2348.                     DestroyFSEntry(&FSe);
  2349.                     }
  2350.                 else
  2351.                     {
  2352.                     FSe->fse_HasSelects = LookUpFSDir(Dir->fsd_Name, FSe->fse_Name);
  2353.  
  2354.                     if (Dir->fsd_DirCount >= Dir->fsd_ListSize)
  2355.                         ExtendFSDir(Dir);
  2356.  
  2357.                     Dir->fsd_EntryList[Dir->fsd_DirCount] = FSe;
  2358.                     ++Dir->fsd_DirCount;
  2359.  
  2360.                     DuplicateOldEntry(Dir, LastDir, FSe);
  2361.  
  2362.                     UnLock(DLLock);
  2363.                     }
  2364.                 }
  2365.             }
  2366.  
  2367.         dlist = NextDosEntry(dlist, DOSLIST_FLAGS);
  2368.         }
  2369.     UnLockDosList(DOSLIST_FLAGS);
  2370.  
  2371.     myProcess->pr_WindowPtr = NULL;
  2372.  
  2373.     if (LastDir)
  2374.         RemoveFSDir(LastDir);
  2375.  
  2376.     Dir->fsd_isComplete = TRUE;
  2377.     SetFSDirListSize(Dir, Dir->fsd_DirCount + 2);
  2378.     SortFSList(Dir);
  2379.  
  2380.     SetBusyPointer(FSwin, FALSE);
  2381.  
  2382.     return Dir;
  2383. }
  2384.  
  2385.  
  2386. static void DuplicateOldEntry(struct FSDir *Dir, struct FSDir *OldDir,
  2387.         struct FSDirEntry *FSe)
  2388. {
  2389.     struct FSDirEntry *FSold;
  2390.  
  2391.     if (OldDir && (FSold = FindFSEntry(FSe->fse_Name, OldDir)))
  2392.         {
  2393.         // Einträge aus altem Directory übernehmen
  2394.         ASSERT_VALID(Dir);
  2395.         ASSERT_VALID(FSe);
  2396.  
  2397.         if (ST_Selected == FSold->fse_Selected)
  2398.             SelectDirEntry(Dir, Dir->fsd_DirCount-1, FSold->fse_ManualSelect != ST_None);
  2399.  
  2400.         FSe->fse_HasSelects = FSold->fse_HasSelects;
  2401.  
  2402.         // Zeiger auf ParentEntry und ParentDir korrigieren
  2403.         if (FSe->fse_Contents = FSold->fse_Contents)
  2404.             {
  2405.             FSe->fse_Contents->fsd_ParentEntry = FSe;
  2406.             }
  2407.         }
  2408. }
  2409.  
  2410.  
  2411. static char *GetFullPathName(BPTR FileLock)
  2412. {
  2413.     char *result = NULL;
  2414.     char *NBuff;
  2415.  
  2416.     ASSERT_VALID(BADDR(FileLock));
  2417.  
  2418.     NBuff = malloc(512);
  2419.     if (NULL == NBuff)
  2420.         return NULL;
  2421.  
  2422.     if (NameFromLock(FileLock, NBuff, 512))
  2423.         result = NBuff;
  2424.     else
  2425.         free(NBuff);
  2426.  
  2427.     return result;
  2428. }
  2429.  
  2430.  
  2431. static void ReSortEntryList(struct FSDir *Dir)
  2432. {
  2433.     ASSERT_VALID(Dir);
  2434.  
  2435.     SortFSList(Dir);
  2436. }
  2437.  
  2438.  
  2439. // Suche im Directory <Dir> nach einem Eintrag mit dem Namen <Name>. Liefert
  2440. // den gefundenen FSDirEntry zurück oder NULL
  2441. static struct FSDirEntry *FindFSEntry(const char *Name, struct FSDir *Dir)
  2442. {
  2443.     short n, found;
  2444.     struct FSDirEntry **FSe, *FSfound;
  2445.  
  2446.     ASSERT_VALID(Name);
  2447.     ASSERT_VALID(Dir);
  2448.  
  2449.     found = FALSE;
  2450.     FSfound = NULL;
  2451.     for (n=0, FSe=Dir->fsd_EntryList; !found && n<Dir->fsd_DirCount; n++, FSe++)
  2452.         {
  2453.         found = stricmp(Name, (*FSe)->fse_Name) == 0;
  2454.         if (found)
  2455.             FSfound = *FSe;
  2456.         }
  2457.  
  2458.     return FSfound;
  2459. }
  2460.  
  2461.  
  2462. void SelectFSEntry(struct FSDir *Dir, struct FSDirEntry *FSe)
  2463. {
  2464.     unsigned short n;
  2465.     short found;
  2466.  
  2467.     ASSERT_VALID(Dir);
  2468.     ASSERT_VALID(FSe);
  2469.  
  2470.     for (n=0, found=FALSE; !found && n<Dir->fsd_DirCount; )
  2471.         {
  2472.         found = Dir->fsd_EntryList[n] == FSe;
  2473.         if (!found)
  2474.             n++;
  2475.         }
  2476.  
  2477.     if (found)
  2478.         {
  2479.         SelectDirEntry(Dir, n, TRUE);
  2480.  
  2481.         if (Dir->fsd_ParentEntry)
  2482.             Dir->fsd_ParentEntry->fse_HasSelects = ManualSelectCount(Dir) > 0;
  2483.         }
  2484. }
  2485.  
  2486.  
  2487. static void SelectDirEntry(struct FSDir *Dir, short n, BOOL Manual)
  2488. {
  2489.     ASSERT_VALID(Dir);
  2490.  
  2491.     InternalSelectEntry(Dir, Dir->fsd_EntryList[n], TRUE, Manual, 0, TRUE);
  2492. }
  2493.  
  2494.  
  2495. static void DeselectDirEntry(struct FSDir *Dir, short n, BOOL Manual)
  2496. {
  2497.     ASSERT_VALID(Dir);
  2498.  
  2499.     InternalSelectEntry(Dir, Dir->fsd_EntryList[n], FALSE, Manual, 0, TRUE);
  2500. }
  2501.  
  2502.  
  2503. static void InternalSelectEntry(struct FSDir *Dir, struct FSDirEntry *FSe,
  2504.     BOOL Select, BOOL Manual, short Level, BOOL Recursive)
  2505. {
  2506.     struct ALVRecordChange RecordChange;
  2507.     BOOL PrevHasSelects;
  2508.     BOOL FSeIsFile;
  2509.  
  2510.     PrevHasSelects = FSe->fse_HasSelects;
  2511.     FSeIsFile = isFile(FSe);
  2512.  
  2513.        if ( !Select && ST_Selected == FSe->fse_Selected)
  2514.         {
  2515.         // Deselektieren
  2516.         FSe->fse_Selected = ST_Deselected;
  2517.  
  2518.         FSe->fse_fsRecord.alr_Flags &= ~ALRF_SELECTED;
  2519.  
  2520.         Dir->fsd_SelectCount--;
  2521.  
  2522.         if (FSeIsFile)
  2523.             {
  2524.             if (Manual)
  2525.                 {
  2526.                 if (ST_Selected == FSe->fse_ManualSelect)
  2527.                     FSFileSelectCount--;
  2528.  
  2529.                 FSe->fse_ManualSelect = Dir->fsd_ParentSelected ? ST_Deselected : ST_None;
  2530.                 }
  2531.             }
  2532.         else
  2533.             {
  2534.             if (Manual)
  2535.                 {
  2536.                 if (ST_Selected == FSe->fse_ManualSelect)
  2537.                     FSDirSelectCount--;
  2538.  
  2539.                 FSe->fse_ManualSelect = Dir->fsd_ParentSelected ? ST_Deselected : ST_None;
  2540.                 }
  2541.  
  2542.             if (Recursive)
  2543.                 SelectChildEntry(Dir, FSe, Level);
  2544.             }
  2545.         }
  2546.     else if (Select && FSe->fse_Selected != ST_Selected )
  2547.         {
  2548.         // Selektieren
  2549.         FSe->fse_Selected = ST_Selected;
  2550.  
  2551.         FSe->fse_fsRecord.alr_Flags |= ALRF_SELECTED;
  2552.  
  2553.         Dir->fsd_SelectCount++;
  2554.  
  2555.         if (Manual)
  2556.             {
  2557.             FSe->fse_ManualSelect = !Dir->fsd_ParentSelected ? ST_Selected : ST_None;
  2558.             }
  2559.  
  2560.         if (FSeIsFile)
  2561.             {
  2562.             if (Manual)
  2563.                 FSFileSelectCount++;
  2564.             }
  2565.         else
  2566.             {
  2567.             struct FSDir *SelectedDir;
  2568.  
  2569.             if (Manual)
  2570.                 FSDirSelectCount++;
  2571.  
  2572.             SelectedDir = CreateFSDir(ConcatDirName(Dir->fsd_Name, FSe->fse_Name), NULL);
  2573.             SelectedDir->fsd_ParentSelected = TRUE;
  2574.             if (SelectedDir->fsd_DirCount == 0)
  2575.                 SelectedDir->fsd_isComplete = FALSE;
  2576.  
  2577.             if (Recursive)
  2578.                 SelectChildEntry(Dir, FSe, Level);
  2579.             }
  2580.         }
  2581.  
  2582.     if (Dir->fsd_ParentEntry)
  2583.         Dir->fsd_ParentEntry->fse_HasSelects = ManualSelectCount(Dir) > 0;
  2584.  
  2585.     if (PrevHasSelects != FSe->fse_HasSelects)
  2586.         {
  2587.         // <HasSelects> hat sich geändert: Anzeige aktualisieren
  2588.         FindAndRedisplayDirEntry(Dir, FSe, 0, 0, RDM_ContentsChanged);
  2589.         }
  2590.  
  2591.     if (!FSeIsFile)
  2592.         {
  2593.         // Anzeige des Select-Marker aktualisieren
  2594.         RecordChange.arc_FirstRecord = &FSe->fse_fsRecord;
  2595.         RecordChange.arc_RecordCount = 1;
  2596.         RecordChange.arc_FirstColumnNo = 0;
  2597.         RecordChange.arc_LastColumnNo = 0;
  2598.         RecordChange.arc_ContentsChanged = FALSE;
  2599.  
  2600.         SetGadgetAttrs(FSGadgets[GDX_FSALVGadget], FSwin, NULL,
  2601.             ALV_InvalidateRecords, &RecordChange,
  2602.             TAG_END);
  2603.         }
  2604. }
  2605.  
  2606.  
  2607. long ManualSelectCount(struct FSDir *Dir)
  2608. {
  2609.     long Result = 0;
  2610.     unsigned long n;
  2611.  
  2612.     if (Dir == NULL)
  2613.         return 0;
  2614.  
  2615.     for (n=0; n<Dir->fsd_DirCount; n++)
  2616.         {
  2617.         if (Dir->fsd_EntryList[n]->fse_ManualSelect != ST_None)
  2618.             Result++;
  2619.         }
  2620.  
  2621.     return Result;
  2622. }
  2623.  
  2624.  
  2625. static void SelectChildEntry(struct FSDir *Dir, struct FSDirEntry *FSe, short Level)
  2626. {
  2627.     unsigned long m;
  2628.     char FullName[FMSIZE];
  2629.     char *NormalizedName;
  2630.     struct FSDir *SubDir;
  2631.     unsigned long index = 0l;
  2632.  
  2633.     if (Level >= 1 && !BackupOpt->bo_IncludeSubDirs)
  2634.         return;
  2635.  
  2636.     NormalizedName = NormalizeName(ConcatDirName(Dir->fsd_Name, FSe->fse_Name));
  2637.     if (NULL == NormalizedName)
  2638.         return;
  2639.  
  2640.     stccpy(FullName, NormalizedName, sizeof(FullName));
  2641.     free(NormalizedName);
  2642.  
  2643.     if (FSe->fse_Contents == NULL)
  2644.         SubDir = LookUpSubDir(FullName, &index);
  2645.     else
  2646.         SubDir = FSe->fse_Contents;
  2647.  
  2648.     do    {
  2649.         if (SubDir == NULL)
  2650.             continue;
  2651.  
  2652.         SubDir->fsd_ParentSelected = FSe->fse_Selected == ST_Selected;
  2653.  
  2654.         for (m=0; m<SubDir->fsd_DirCount; m++)
  2655.             {
  2656.             if (SubDir->fsd_EntryList[m]->fse_ManualSelect == ST_None &&
  2657.                     FSFileMatch(BackupOpt, SubDir->fsd_EntryList[m]))
  2658.                 {
  2659.                 // Da durch die do {} Schleife bereits ALLE Subdirectories
  2660.                 // durchgegangen werden, wird hier NICHT REKURSIV Selektiert !
  2661.                 InternalSelectEntry(SubDir, SubDir->fsd_EntryList[m],
  2662.                     FSe->fse_Selected == ST_Selected,
  2663.                     FALSE, Level+1, FALSE);
  2664.                 }
  2665.             }
  2666.  
  2667.         SetFSHasSelects(SubDir);
  2668.  
  2669.         if (SubDir == aktFSDir)
  2670.             {
  2671.             DisplayFSList(aktFSDir);
  2672.             }
  2673.  
  2674.         SubDir = LookUpSubDir(FullName, &index);
  2675.         } while (SubDir);
  2676. }
  2677.  
  2678.  
  2679. // mit String-Operationen wird der Name des Parent Directory aus <DirName> ermittelt.
  2680. static char *FindParentName(char *DirName)
  2681. {
  2682.     char *Trenn;
  2683.  
  2684.     ASSERT_VALID(DirName);
  2685.     DirName = strdup(DirName);
  2686.     if (DirName == NULL)
  2687.         {
  2688.         alarm(GetString(MSG_OUTOFMEMORY), __FUNC__, "DirName", strlen(DirName));
  2689.         myabort(10);
  2690.         }
  2691.  
  2692.     if (strlen(DirName) < 2)
  2693.         {
  2694.         *DirName = '\0';
  2695.         return DirName;
  2696.         }
  2697.  
  2698.     Trenn = DirName + strlen(DirName) - 2;    // auf vorletztes Zeichen zeigen
  2699.     while (Trenn != DirName && *Trenn != ':' && *Trenn != '/')
  2700.         Trenn--;
  2701.  
  2702.     if (Trenn == DirName)
  2703.         {
  2704.         *DirName = '\0';
  2705.         return DirName;
  2706.         }
  2707.  
  2708.     if (*Trenn == '/')
  2709.         *Trenn = '\0';
  2710.     else
  2711.         Trenn[1] = '\0';
  2712.  
  2713.     return DirName;
  2714. }
  2715.  
  2716.  
  2717. static void SelectFSAttr(BOOL Select)
  2718. {
  2719.     struct FileInfoBlock __aligned fib;
  2720.     struct ALVRecordChange RecordChange;
  2721.     long fromDate, toDate;
  2722.     short found, n;
  2723.  
  2724.     GetPatternGadgetString();
  2725.  
  2726.     fromDate = ReadDate(GADSTRING(FSGadgets[GDX_FSFromDateGadget]));
  2727.     toDate = ReadDate(GADSTRING(FSGadgets[GDX_FSToDateGadget]));
  2728.  
  2729.     if (BackupOpt->bo_UseGrepPattern && !SelectPattern.isParsed)
  2730.         {
  2731.         if (ParsePatternNoCase(SelectPattern.RawName,
  2732.                 SelectPattern.ParsedPattern,
  2733.                 sizeof(SelectPattern.ParsedPattern) ) == -1)
  2734.             {
  2735.             alarm("%s: %s", __FUNC__, GetString(MSG_XLATEERROR_SELECT));
  2736.             SelectPattern.isParsed = FALSE;
  2737.             }
  2738.         else
  2739.             SelectPattern.isParsed = TRUE;
  2740.         }
  2741.  
  2742.     for (n=0; n<aktFSDir->fsd_DirCount; n++)
  2743.         {
  2744.         // wahlweise mit eigenem PatternMatch (*,?) oder mit dem
  2745.         // besseren PatternMatcher des DOS2.0 arbeiten
  2746.         if (BackupOpt->bo_UseGrepPattern && SelectPattern.isParsed)
  2747.             {
  2748.             found = MatchPatternNoCase(SelectPattern.ParsedPattern,
  2749.                     aktFSDir->fsd_EntryList[n]->fse_Name);
  2750.             }
  2751.         else
  2752.             {
  2753.             stccpy(fib.fib_FileName, aktFSDir->fsd_EntryList[n]->fse_Name,
  2754.                     sizeof(fib.fib_FileName)-1);
  2755.             found = FileNamePatternMatch(SelectPattern.RawName, &fib);
  2756.             }
  2757.  
  2758.         // nach Archiv-Bit
  2759.         switch (FSArchiveSelect)
  2760.             {
  2761.         case ARCSEL_Cleared:
  2762.             found = found && !(aktFSDir->fsd_EntryList[n]->fse_Protection & FIBF_ARCHIVE);
  2763.             break;
  2764.         case ARCSEL_Set:
  2765.             found = found && (aktFSDir->fsd_EntryList[n]->fse_Protection & FIBF_ARCHIVE);
  2766.             break;
  2767.             }
  2768.  
  2769.         // nach Datum
  2770.         found = found
  2771.             && (aktFSDir->fsd_EntryList[n]->fse_Date.ds_Days >= fromDate
  2772.             || !(FSGadgets[GDX_FSFromOnGadget]->Flags & GFLG_SELECTED))
  2773.             && (aktFSDir->fsd_EntryList[n]->fse_Date.ds_Days <  toDate
  2774.             || !(FSGadgets[GDX_FSToOnGadget]->Flags & GFLG_SELECTED));
  2775.  
  2776.         if (found)
  2777.             {
  2778.             if (Select)
  2779.                 SelectDirEntry(aktFSDir, n, TRUE);
  2780.             else
  2781.                 DeselectDirEntry(aktFSDir, n, TRUE);
  2782.             }
  2783.         }
  2784.  
  2785.     if (aktFSDir->fsd_ParentEntry)
  2786.         aktFSDir->fsd_ParentEntry->fse_HasSelects = ManualSelectCount(aktFSDir) > 0;
  2787.  
  2788.     GetAttr(ALV_Records, FSGadgets[GDX_FSALVGadget], (ULONG *) &RecordChange.arc_FirstRecord);
  2789.     RecordChange.arc_RecordCount = ULONG_MAX;
  2790.     RecordChange.arc_FirstColumnNo = 0;
  2791.     RecordChange.arc_LastColumnNo = ULONG_MAX;
  2792.     RecordChange.arc_ContentsChanged = FALSE;
  2793.  
  2794.     SetGadgetAttrs(FSGadgets[GDX_FSALVGadget], FSwin, NULL,
  2795.         ALV_InvalidateRecords, &RecordChange,
  2796.         TAG_END);
  2797. }
  2798.  
  2799.  
  2800. // aus den beiden Namensteilen <ParentName> und <DirName> wird ein gültiger Pfadname erzeugt.
  2801. char *ConcatDirName(const char *ParentName, char *DirName)
  2802. {
  2803.     size_t len;
  2804.     char *NewDirName;
  2805.  
  2806.     ASSERT_VALID(ParentName);
  2807.     ASSERT_VALID(DirName);
  2808.  
  2809.     len = strlen(ParentName) + strlen(DirName) + 3;
  2810.     NewDirName = malloc(len);
  2811.     if (NewDirName == NULL)
  2812.         {
  2813.         alarm(GetString(MSG_OUTOFMEMORY), __FUNC__, "NewDirName", len);
  2814.         myabort(10);
  2815.         }
  2816.  
  2817.     strcpy(NewDirName, ParentName);
  2818.     AddPart(NewDirName, DirName, len);
  2819.  
  2820.     return NewDirName;
  2821. }
  2822.  
  2823.  
  2824. /* Suche, ob das Subdirectory <DirName> im Directory <ParentName> 
  2825.    oder irgendwelche Subdirectories von <DirName> bereits
  2826.    in BackupOpt->bo_FSDirList eingetragen sind.
  2827.    Werden Einträge gefunden, wird nach den HasSelects geschaut.
  2828.    Liefert TRUE zurück, wenn irgendwelche Subdirectories mit HasSelects != 0
  2829.    gefunden wurden, sonst FALSE.
  2830. */
  2831. static BOOL LookUpFSDir(char *ParentName, char *DirName)
  2832. {
  2833.     char *ccParentName, *FullParentName;
  2834.     struct FSDir **dir;
  2835.     unsigned long n;
  2836.     BOOL result=FALSE;
  2837.  
  2838.     ASSERT_VALID(ParentName);
  2839.     ASSERT_VALID(DirName);
  2840.  
  2841.     ccParentName = ConcatDirName(ParentName, DirName);
  2842.     FullParentName = NormalizeName(ccParentName);
  2843.  
  2844.     for (n=0, dir=BackupOpt->bo_FSDirList; !result && n<BackupOpt->bo_FSDirCount; n++, dir++)
  2845.         {
  2846.         if (isChildOf(FullParentName, (*dir)->fsd_Name))
  2847.             result |= (*dir)->fsd_HasSelects || ManualSelectCount(*dir);
  2848.         }
  2849.  
  2850.     free(FullParentName);
  2851.     free(ccParentName);
  2852.  
  2853.     return result;
  2854. }
  2855.  
  2856.  
  2857. /* Suche, ob das Directory <DirName> 
  2858.    oder irgendwelche Subdirectories von <DirName> bereits
  2859.    in BackupOpt->bo_FSDirList eingetragen sind.
  2860.    Liefert den Eintrag zurück, wenn irgendwelche Subdirectories
  2861.    gefunden wurden, sonst FALSE.
  2862. */
  2863. static struct FSDir *LookUpSubDir(char *ParentName, unsigned long *n)
  2864. {
  2865.     struct FSDir **dir;
  2866.     short found;
  2867.  
  2868.     ASSERT_VALID(ParentName);
  2869.  
  2870.     for (found=FALSE, dir=&BackupOpt->bo_FSDirList[*n]; !found && *n<BackupOpt->bo_FSDirCount; (*n)++)
  2871.         {
  2872.         found = stricmp(ParentName, (*dir)->fsd_Name) == 0 ||
  2873.             isChildOf(ParentName, (*dir)->fsd_Name);
  2874.  
  2875.         if (!found)
  2876.             dir++;
  2877.         }
  2878.  
  2879.     return found ? (*dir) : NULL;
  2880. }
  2881.  
  2882.  
  2883. /* Suche, ob irgendwelche Parent Directories von <DirName> bereits
  2884.    in BackupOpt->bo_FSDirList eingetragen sind.
  2885.    Liefert den passenden Eintrag zurück, wenn irgendwelche 
  2886.    Parent Directories gefunden wurden, sonst NULL.
  2887. */
  2888. static struct FSDir *LookUpParentDir(const char *SubDirName, unsigned long *n)
  2889. {
  2890.     struct FSDir **dir;
  2891.     BOOL found;
  2892.  
  2893.     ASSERT_VALID(SubDirName);
  2894.  
  2895.     for (found=FALSE,dir=&BackupOpt->bo_FSDirList[*n]; !found && 
  2896.             (*n)<BackupOpt->bo_FSDirCount; (*n)++)
  2897.         {
  2898.         found = isChildOf((*dir)->fsd_Name, SubDirName);
  2899.  
  2900.         if (!found)
  2901.             dir++;
  2902.         }
  2903.  
  2904.     return found ? *dir : NULL;
  2905. }
  2906.  
  2907.  
  2908. // Suchen in BackupOpt->bo_FSDirList nach Directory <DirName>
  2909. struct FSDir *SearchFSDir(const char *DirName)
  2910. {
  2911.     struct FSDir **dir;
  2912.     short found;
  2913.     unsigned long n;
  2914.  
  2915.     ASSERT_VALID(DirName);
  2916.  
  2917.     for (n=0, dir=BackupOpt->bo_FSDirList, found=0; !found && n<BackupOpt->bo_FSDirCount; n++)
  2918.         {
  2919.         found = stricmp(DirName, (*dir)->fsd_Name) == 0;
  2920.         if (!found)
  2921.             dir++;
  2922.         }
  2923.  
  2924.     return found ? *dir : NULL;
  2925. }
  2926.  
  2927.  
  2928. static void EmptyFSDir(struct FSDir *dir)
  2929. {
  2930.     unsigned long n;
  2931.  
  2932.     ASSERT_VALID(dir);
  2933.  
  2934.     for (n=0; n<dir->fsd_DirCount; n++)
  2935.         {
  2936.         DestroyFSEntry(&dir->fsd_EntryList[n]);
  2937.         }
  2938.  
  2939.     dir->fsd_DirCount = 0;
  2940.     dir->fsd_SelectCount = 0;
  2941. }
  2942.  
  2943.  
  2944. /* Alle Einträge im Directory <Dir> prüfen, ob HasSelects dort gesetzt ist,
  2945.    und entsprechend Dir->fse_HasSelects setzen.
  2946. */
  2947. static short SetFSHasSelects(struct FSDir *Dir)
  2948. {
  2949.     unsigned long n;
  2950.  
  2951.     ASSERT_VALID(Dir);
  2952.     Dir->fsd_HasSelects = FALSE;
  2953.  
  2954.     for (n=0; !Dir->fsd_HasSelects && n<Dir->fsd_DirCount; n++)
  2955.         {
  2956.         struct FSDirEntry *FSe;
  2957.  
  2958.         FSe = Dir->fsd_EntryList[n];
  2959.  
  2960.         // hier werden manuelle Selekts aufgehoben, wenn sie mit dem ParentSelect übereinstimmen
  2961.         if (Dir->fsd_ParentSelected)
  2962.             {
  2963.             if (ST_Selected == FSe->fse_ManualSelect)
  2964.                 FSe->fse_ManualSelect = ST_None;
  2965.             }
  2966.         else
  2967.             {
  2968.             if (ST_Deselected == FSe->fse_ManualSelect)
  2969.                 FSe->fse_ManualSelect = ST_None;
  2970.             }
  2971.  
  2972.         if (!isFile(FSe))
  2973.             {
  2974.             // Volume oder Directory
  2975.             Dir->fsd_HasSelects |= FSe->fse_HasSelects;
  2976.             }
  2977.         }
  2978.  
  2979.     return (short) Dir->fsd_HasSelects;
  2980. }
  2981.  
  2982.  
  2983. static BOOL isleap(short year)
  2984. {
  2985.     return (BOOL)(((year % 4) == 0) && ((year % 100) != 0 || (year % 400) == 0));
  2986. }
  2987.  
  2988.  
  2989. char *GetFileFlags(long Flags)
  2990. {
  2991.     static char prot[9];
  2992.     static const char protnames[] = "hsparwed";
  2993.     short i;
  2994.  
  2995.     Flags ^= 0x0f;
  2996.     for (i=0; i<strlen(protnames); i++)
  2997.         prot[i] = (Flags & (0x80 >> i)) ? protnames[i] : '-';
  2998.     prot[i] = '\0';
  2999.  
  3000.     return prot;
  3001. }
  3002.  
  3003.  
  3004. // vertauscht den Inhalt der String-Gadgets <Gad1> und <Gad2>
  3005. void SwapFromToDate(struct Window *Win, struct Gadget *Gad1, struct Gadget *Gad2)
  3006. {
  3007.     char *tempFrom, *tempTo;
  3008.  
  3009.     ASSERT_VALID(Win);
  3010.     ASSERT_VALID(Gad1);
  3011.     ASSERT_VALID(Gad2);
  3012.  
  3013.     tempFrom = strdup(GADSTRING(Gad1));
  3014.     if (tempFrom == NULL)
  3015.         return;
  3016.  
  3017.     tempTo = strdup(GADSTRING(Gad2));
  3018.     if (tempTo == NULL)
  3019.         {
  3020.         free(tempFrom);
  3021.         return;
  3022.         }
  3023.  
  3024.     GT_SetGadgetAttrs(Gad1, Win, NULL,
  3025.         GTST_String, tempTo,
  3026.         TAG_END);
  3027.     GT_SetGadgetAttrs(Gad2, Win, NULL,
  3028.         GTST_String, tempFrom,
  3029.         TAG_END);
  3030.  
  3031.     free(tempFrom);
  3032.     free(tempTo);
  3033. }
  3034.  
  3035.  
  3036. // Einstellung aller Gadgets für die Sicherung ahand der Werte in <NewOpts>
  3037. static void SetupBackupOpts(struct BackupOptions *NewOpts, const char *NewCmdFileName)
  3038. {
  3039.     struct myDate date;
  3040.  
  3041.     ASSERT_VALID(NewOpts);
  3042.     ASSERT_VALID(NewCmdFileName);
  3043.  
  3044.     strcpy(CmdFileName, NewCmdFileName);
  3045.  
  3046.     // Datums-Strings vorbelegen
  3047.     UnpackDate(NewOpts->bo_FirstDate, &date);
  3048.     GT_SetGadgetAttrs(FSGadgets[GDX_FSFromDateGadget], FSwin, NULL,
  3049.         GTST_String, DateString(date.Day, date.Month, date.Year),
  3050.         TAG_END);
  3051.  
  3052.     UnpackDate(NewOpts->bo_LastDate, &date);
  3053.     GT_SetGadgetAttrs(FSGadgets[GDX_FSToDateGadget], FSwin, NULL,
  3054.         GTST_String, DateString(date.Day, date.Month, date.Year),
  3055.         TAG_END);
  3056.  
  3057.     ShowWildcardOpt(NewOpts);
  3058.     TranslateWildCards(NewOpts);
  3059.     SetMenus(NewOpts);
  3060. }
  3061.  
  3062.  
  3063. static void DisplaySelectCount(void)
  3064. {
  3065.     static unsigned long LastFileSelectCount = ~0;
  3066.     static unsigned long LastDirSelectCount = ~0;
  3067.     static char WinTitle[100];
  3068.  
  3069.     if (LastFileSelectCount != FSFileSelectCount ||
  3070.             LastDirSelectCount != FSDirSelectCount)
  3071.         {
  3072.         sprintf(WinTitle,
  3073.             GetString(MSG_FSWIN_TITLE),
  3074.             FSDirSelectCount,
  3075.             GetString(FSDirSelectCount == 1 ? MSG_FSWIN_TITLE_DIR1 : MSG_FSWIN_TITLE_DIR2),
  3076.             FSFileSelectCount,
  3077.             GetString(FSFileSelectCount == 1 ? MSG_FSWIN_TITLE_FILE1 : MSG_FSWIN_TITLE_FILE2)
  3078.             );
  3079.  
  3080.         SetWindowTitles(FSwin, WinTitle, (UBYTE *) ~0);
  3081.  
  3082.         LastFileSelectCount = FSFileSelectCount;
  3083.         LastDirSelectCount = FSDirSelectCount;
  3084.         }
  3085.  
  3086.     // Start-Gadget disabled wenn nichts selektiert
  3087.     GT_SetGadgetAttrs(FSGadgets[GDX_FSStartGadget], FSwin, NULL,
  3088.         GA_Disabled, 0 == (FSFileSelectCount + FSDirSelectCount),
  3089.         TAG_END);
  3090. }
  3091.  
  3092.  
  3093. void TranslateWildCards(struct BackupOptions *BackupOpt)
  3094. {
  3095.     if (BackupOpt->bo_UseGrepPattern)
  3096.         {
  3097.         if (strcmp(SelectPattern.RawName, "*") == 0)
  3098.             strcpy(SelectPattern.RawName, "#?");
  3099.  
  3100.         if (strcmp(BackupOpt->bo_IncludeFile.RawName, "*") == 0)
  3101.             strcpy(BackupOpt->bo_IncludeFile.RawName, "#?");
  3102.         if (strcmp(BackupOpt->bo_ExcludeFile.RawName, "*") == 0)
  3103.             strcpy(BackupOpt->bo_ExcludeFile.RawName, "#?");
  3104.         }
  3105.     else
  3106.         {
  3107.         if (strcmp(SelectPattern.RawName, "#?") == 0)
  3108.             strcpy(SelectPattern.RawName, "*");
  3109.  
  3110.         if (strcmp(BackupOpt->bo_IncludeFile.RawName, "#?") == 0)
  3111.             strcpy(BackupOpt->bo_IncludeFile.RawName, "*");
  3112.         if (strcmp(BackupOpt->bo_ExcludeFile.RawName, "#?") == 0)
  3113.             strcpy(BackupOpt->bo_ExcludeFile.RawName, "*");
  3114.         }
  3115.  
  3116.     if (FSGadgets)
  3117.         {
  3118.         GT_SetGadgetAttrs(FSGadgets[GDX_FSPatternGadget], FSwin, NULL,
  3119.             GTST_String, SelectPattern.RawName,
  3120.             TAG_END);
  3121.         }
  3122.  
  3123.     SelectPattern.isParsed = FALSE;
  3124.     BackupOpt->bo_IncludeFile.isParsed = FALSE;
  3125.     BackupOpt->bo_ExcludeFile.isParsed = FALSE;
  3126. }
  3127.  
  3128.  
  3129. static void EnableGOGadget(void)
  3130. {
  3131.     if (FSwin)
  3132.         {
  3133.         GT_SetGadgetAttrs(FSGadgets[GDX_FSGlobOptGadget], FSwin, NULL,
  3134.             GA_Disabled, FALSE,
  3135.             TAG_END);
  3136.         }
  3137. }
  3138.  
  3139.  
  3140. static short isFile(const struct FSDirEntry *FS)
  3141. {
  3142.     short result;
  3143.  
  3144.     ASSERT_VALID(FS);
  3145.  
  3146.     switch (FS->fse_Typ)
  3147.         {
  3148.     case File:
  3149.     case HardLinkFile:
  3150.     case SoftLinkFile:
  3151.     case Device:
  3152.         result = TRUE;
  3153.         break;
  3154.     case Directory:
  3155.     case Assign:
  3156.     case Volume:
  3157.     case SoftLinkDir:
  3158.     case HardLinkDir:
  3159.         result = FALSE;
  3160.         break;
  3161.         }
  3162.  
  3163.     return result;
  3164. }
  3165.  
  3166.  
  3167. /* Untersuchen, ob ein SoftLink zu einem Directory oder einem File gehört.
  3168.    Liefert je nachdem "SoftLinkFile" oder "SoftLinkDir" zurück.
  3169.    kann getrost DOS V37+ Funktionen benutzen, da bei älteren Funktionen
  3170.    sowieso keine SoftLinks erkannt werden.
  3171. */
  3172. enum FType SoftLinkType(const STRPTR Name, BPTR DirLock)
  3173. {
  3174.     static struct FileInfoBlock __aligned SLfib;
  3175.  
  3176.     ASSERT_VALID(Name);
  3177.     ASSERT_VALID(BADDR(DirLock));
  3178.  
  3179.     if (!ResolveSoftLink(Name, DirLock, &SLfib))
  3180.         return SoftLinkDir;
  3181.     else
  3182.         return SLfib.fib_DirEntryType >= 0 ? SoftLinkDir : SoftLinkFile;
  3183. }
  3184.  
  3185.  
  3186. // Auflösen eines SoftLinks - wenn nötig rekursiv
  3187. short ResolveSoftLink(const STRPTR LinkName, BPTR DirLock, struct FileInfoBlock *LinkFib)
  3188. {
  3189.     char SoftLinkPath[FMSIZE];
  3190.     char PathName[FMSIZE];
  3191.     BPTR SLock;
  3192.  
  3193.     ASSERT_VALID(LinkName);
  3194.     ASSERT_VALID(BADDR(DirLock));
  3195.     ASSERT_VALID(LinkFib);
  3196.  
  3197.     if (!NameFromLock(DirLock, PathName, sizeof(PathName)))
  3198.         {
  3199.         PostError(TRUE, MSGPRI_Error, GetString(MSG_NAMEFROMLOCK_FAILED_RSL), PathName);
  3200.         return FALSE;
  3201.         }
  3202.  
  3203.     do    {
  3204.         if (!ReadLink(DeviceProc(PathName), DirLock,
  3205.                 (STRPTR) LinkName, SoftLinkPath, sizeof(SoftLinkPath)) )
  3206.             {
  3207.             PostError(TRUE, MSGPRI_Error, GetString(MSG_READLINK_FAILED_RSL), SoftLinkPath);
  3208.  
  3209.             return FALSE;
  3210.             }
  3211.         SLock = Lock(SoftLinkPath, ACCESS_READ);
  3212.         Examine(SLock, LinkFib);
  3213.         UnLock(SLock);
  3214.  
  3215.         strcpy(PathName, SoftLinkPath);
  3216.         } while (LinkFib->fib_DirEntryType == ST_SOFTLINK);
  3217.  
  3218.     return TRUE;
  3219. }
  3220.  
  3221.  
  3222. void LoadCmdFile(struct Window *Win, char *LoadCmdFileName,
  3223.         struct BackupOptions *Opt)
  3224. {
  3225.     struct FSDir **Dir;
  3226.     char *path;
  3227.     unsigned long n, m;
  3228.     short Ok;
  3229.  
  3230.     ASSERT_VALID(Win);
  3231.     ASSERT_VALID(LoadCmdFileName);
  3232.     ASSERT_VALID(Opt);
  3233.  
  3234.     // Alle Einträge deselektieren
  3235.     for (n=0, Dir=Opt->bo_FSDirList; n<Opt->bo_FSDirCount; n++, Dir++)
  3236.         {
  3237.         for (m=0; m<(*Dir)->fsd_DirCount; m++)
  3238.             {
  3239.             DeselectDirEntry(*Dir, m, TRUE);
  3240.             (*Dir)->fsd_EntryList[m]->fse_HasSelects = FALSE;
  3241.             }
  3242.         (*Dir)->fsd_SelectCount = 0;
  3243.         (*Dir)->fsd_HasSelects = FALSE;
  3244.         }
  3245.  
  3246.     DefaultOptions(Opt, 0);        // alles auf default-Werte
  3247.  
  3248.     // ggf. Argumente aus .info übernehmen
  3249.     Ok = CheckDiskObject(LoadCmdFileName, Opt);
  3250.  
  3251.     if (Ok && OpenCmdFile(LoadCmdFileName))
  3252.         {
  3253.         do    {
  3254.             path = ReadCmdFile(Opt, 0);
  3255.             } while (path);
  3256.  
  3257.         CloseCmdFile();
  3258.         RefreshXGO(Opt);
  3259.         }
  3260.  
  3261.     SetupBackupOpts(Opt, LoadCmdFileName);
  3262.     DisplaySelectCount();
  3263. }
  3264.  
  3265.  
  3266. // Icon wurde im FS-Window oder im GO-Window fallengelassen
  3267. static void UseDiskObject(struct AppMessage *AppMsg)
  3268. {
  3269.     unsigned long n;
  3270.  
  3271.     ASSERT_VALID(AppMsg);
  3272.  
  3273.     if (AppMsg->am_ID == AMID_FILESELECT && isInFileView(AppMsg->am_MouseX, AppMsg->am_MouseY))
  3274.         {
  3275.         // Drop innerhalb des File-Window
  3276.         AddFSEntries(AppMsg);
  3277.         }
  3278.     else
  3279.         {
  3280.         // Drop im GO-Window oder außerhalb des File-Window => Kommandofile
  3281.         ClearSettings(FALSE);
  3282.  
  3283.         n = AppMsg->am_NumArgs;        // Anzahl Argumente
  3284.  
  3285.         if (n > 0)
  3286.             {
  3287.             BPTR OldLock;
  3288.             short Ok;
  3289.  
  3290.             OldLock = CurrentDir(DupLock(AppMsg->am_ArgList[0].wa_Lock));
  3291.  
  3292.             Ok = CheckDiskObject(AppMsg->am_ArgList[0].wa_Name, BackupOpt);
  3293.  
  3294.             if (Ok && OpenCmdFile(AppMsg->am_ArgList[0].wa_Name))
  3295.                 {
  3296.                 char *path;
  3297.                 BPTR CmdFileLock;
  3298.  
  3299.                 // Name des geladenen Kommandofiles merken
  3300.                 CmdFileLock = Lock(AppMsg->am_ArgList[0].wa_Name, ACCESS_READ);
  3301.                 if (CmdFileLock)
  3302.                     {
  3303.                     NameFromLock(CmdFileLock, CmdFileName, sizeof(CmdFileName));
  3304.  
  3305.                     // Pfad des Kommandofiles in <BackupOpt->bo_ScriptPath> übernehmen
  3306.                     stcgfp(BackupOpt->bo_ScriptPath, CmdFileName);
  3307.                     AddPart(BackupOpt->bo_ScriptPath, (STRPTR) "", sizeof(BackupOpt->bo_ScriptPath));
  3308.  
  3309.                     UnLock(CmdFileLock);
  3310.                     }
  3311.                 else
  3312.                     stccpy(CmdFileName, AppMsg->am_ArgList[0].wa_Name,
  3313.                         sizeof(CmdFileName));
  3314.  
  3315.  
  3316.                 do    {
  3317.                     path = ReadCmdFile(BackupOpt, 0);
  3318.                     } while (path);
  3319.  
  3320.                 CloseCmdFile();
  3321.                 RefreshXGO(BackupOpt);
  3322.                 }
  3323.             UnLock(CurrentDir(OldLock));    // Current Dir restaurieren
  3324.             }
  3325.         SetupBackupOpts(BackupOpt, CmdFileName);
  3326.         }
  3327.     DisplaySelectCount();
  3328. }
  3329.  
  3330.  
  3331. void ClearSettings(BOOL Show)
  3332. {
  3333.     struct FSDir **Dir;
  3334.     short m, n;
  3335.  
  3336.     strcpy(CmdFileName, "");    // kein Kommandofile
  3337.  
  3338.     // Alle Einträge deselektieren
  3339.     for (n=0, Dir=BackupOpt->bo_FSDirList; n<BackupOpt->bo_FSDirCount; n++, Dir++)
  3340.         {
  3341.         for (m=0; m<(*Dir)->fsd_DirCount; m++)
  3342.             {
  3343.             struct FSDirEntry *FSe;
  3344.             BOOL OldSelect, OldHasSelects;
  3345.  
  3346.             FSe = (*Dir)->fsd_EntryList[m];
  3347.  
  3348.             OldSelect = FSe->fse_Selected;
  3349.             OldHasSelects = FSe->fse_HasSelects;
  3350.  
  3351.             DeselectDirEntry(*Dir, m, FALSE);
  3352.  
  3353.             FSe->fse_HasSelects = FALSE;
  3354.             FSe->fse_ManualSelect = ST_None;
  3355.  
  3356.             // Anzeige aktualisieren
  3357.             if (OldHasSelects != FSe->fse_HasSelects)
  3358.                 FindAndRedisplayDirEntry(*Dir, FSe, 0, 0, RDM_ContentsChanged);
  3359.             if (OldSelect != FSe->fse_Selected)
  3360.                 FindAndRedisplayDirEntry(*Dir, FSe, 0, ULONG_MAX, RDM_FlagsChanged);
  3361.             }
  3362.         (*Dir)->fsd_SelectCount = 0;
  3363.         (*Dir)->fsd_HasSelects = FALSE;
  3364.         }
  3365.  
  3366.     FSFileSelectCount = 0l;
  3367.     FSDirSelectCount = 0l;
  3368.  
  3369.     DefaultOptions(BackupOpt, 0);        // alles auf default-Werte
  3370.  
  3371.     if (Show)
  3372.         {
  3373.         RefreshXGO(BackupOpt);
  3374.         DisplaySelectCount();
  3375.         }
  3376. }
  3377.  
  3378.  
  3379. static void AddFSEntries(struct AppMessage *AppMsg)
  3380. {
  3381.     static struct FileInfoBlock __aligned fib;
  3382.     char DirName[FMSIZE];
  3383.     struct FSDir *Dir, **pDir;
  3384.     struct FSDirEntry *FSe;
  3385.     BPTR OldLock, FileLock;
  3386.     long m, n;
  3387.  
  3388.     ASSERT_VALID(AppMsg);
  3389.  
  3390.     for (n=0; n<AppMsg->am_NumArgs; n++)
  3391.         {
  3392.         OldLock = CurrentDir(DupLock(AppMsg->am_ArgList[n].wa_Lock));
  3393.  
  3394.         FileLock = Lock(AppMsg->am_ArgList[n].wa_Name, ACCESS_READ);
  3395.         if (!FileLock)
  3396.             {
  3397.             alarm(GetString(MSG_LOCK_FAILURE), __FUNC__,
  3398.                 ShortFileName(AppMsg->am_ArgList[n].wa_Name, 60), GetIoErrText() );
  3399.             break;
  3400.             }
  3401.         Examine(FileLock, &fib);
  3402.         if (!NameFromLock(AppMsg->am_ArgList[n].wa_Lock, DirName, sizeof(DirName)))
  3403.             {
  3404.             alarm(GetString(MSG_NAMEFROMLOCK_FAILURE),
  3405.                 ShortFileName(AppMsg->am_ArgList[n].wa_Name, 60),
  3406.                 GetIoErrText() );
  3407.             break;
  3408.             }
  3409.         if (AppMsg->am_ArgList[n].wa_Name[0])
  3410.             {
  3411.             Dir = CreateFSDir(DirName, NULL);
  3412.             FSe = AddFSEntry(Dir, AppMsg->am_ArgList[n].wa_Name, GetFibType(fib.fib_EntryType, fib.fib_FileName, AppMsg->am_ArgList[n].wa_Lock));
  3413.             }
  3414.         else
  3415.             {
  3416.             char *ParentName;
  3417.  
  3418.             ParentName = FindParentName(DirName);
  3419.             Dir = CreateFSDir(ParentName, NULL);
  3420.             FSe = AddFSEntry(Dir, NurName(DirName), GetFibType(fib.fib_EntryType, fib.fib_FileName, AppMsg->am_ArgList[n].wa_Lock));
  3421.             free(ParentName);
  3422.             }
  3423.  
  3424.         SelectFSEntry(Dir, FSe);
  3425.         FindAndRedisplayDirEntry(Dir, FSe, 0l, ULONG_MAX, RDM_FlagsChanged);
  3426.  
  3427.         if (OldLock)
  3428.             UnLock(CurrentDir(OldLock));    // Current Dir restaurieren
  3429.         if (FileLock)
  3430.             UnLock(FileLock);
  3431.         }
  3432.  
  3433.     // Jetzt überall die <HasSelects> korrigieren
  3434.     for (n=0, pDir=BackupOpt->bo_FSDirList; n<BackupOpt->bo_FSDirCount; n++, pDir++)
  3435.         {
  3436.         for (m=0; m<(*pDir)->fsd_DirCount; m++)
  3437.             {
  3438.             FSe = (*pDir)->fsd_EntryList[m];
  3439.  
  3440.             if (!isFile(FSe))
  3441.                 {
  3442.                 short OldHasSelects;
  3443.  
  3444.                 OldHasSelects = FSe->fse_HasSelects;
  3445.                 FSe->fse_HasSelects = LookUpFSDir((*pDir)->fsd_Name, FSe->fse_Name);
  3446.  
  3447.                 // sichtbare Änderungen sofort anzeigen
  3448.                 if (OldHasSelects != FSe->fse_HasSelects)
  3449.                     FindAndRedisplayDirEntry(*pDir, FSe, 0l, 0l, RDM_ContentsChanged);
  3450.                 }
  3451.             }
  3452.         }
  3453. }
  3454.  
  3455.  
  3456. void ToggleHelp(void)
  3457. {
  3458.     if (HelpActive)
  3459.         StopHelp();
  3460.     else
  3461.         StartHelp();
  3462. }
  3463.  
  3464.  
  3465. void StartHelp(void)
  3466. {
  3467.     ASSERT_VALID(activeWindow);
  3468.  
  3469.     HelpControl(activeWindow, HC_GADGETHELP);
  3470.  
  3471. //???    SelectGadget(&FSWinHelpGadget, FSwin, NULL, TRUE);
  3472.  
  3473.     HelpActive = TRUE;
  3474.     SetHelpPointer(activeWindow, TRUE);
  3475.  
  3476.     if (!CallHelp(0L, TRUE))
  3477.         {
  3478.         // Hilfe nicht verfügbar
  3479.         StopHelp();
  3480.  
  3481. //???        SelectGadget(&FSWinHelpGadget, FSwin, NULL, FALSE);
  3482.         }
  3483. }
  3484.  
  3485.  
  3486. void StopHelp(void)
  3487. {
  3488.     if (GadgetHelp)
  3489.         HelpControl(activeWindow, 0);
  3490.  
  3491.     SetHelpPointer(activeWindow, FALSE);
  3492.  
  3493.     CloseHelp();
  3494.  
  3495. //???    SelectGadget(&FSWinHelpGadget, FSwin, NULL, FALSE);
  3496.  
  3497.     HelpActive = FALSE;
  3498. }
  3499.  
  3500.  
  3501. static BOOL isChildOf(const char *Parent, const char *Child)
  3502. {
  3503.     size_t len;
  3504.  
  3505.     len = strlen(Parent);
  3506.     if (strnicmp(Parent, Child, len) != 0)
  3507.         return FALSE;
  3508.  
  3509.     if (Parent[len-1] == ':')
  3510.         return TRUE;
  3511.  
  3512.     if (Child[len] != '/')
  3513.         return FALSE;
  3514.  
  3515.     return TRUE;
  3516. }
  3517.  
  3518.  
  3519. static size_t InsertFSe(struct FSDir *Dir, struct FSDirEntry *FSe)
  3520. {
  3521.     size_t InsertIndex, Index;
  3522.  
  3523.     // ggf. die Liste verlängern !
  3524.     if (Dir->fsd_DirCount >= Dir->fsd_ListSize)
  3525.         ExtendFSDir(Dir);
  3526.  
  3527.     InsertIndex = 0l;
  3528.     while (InsertIndex < Dir->fsd_DirCount && 
  3529.         (*BackupOpt->bo_FSCompare)(&Dir->fsd_EntryList[InsertIndex], &FSe) < 0)
  3530.         InsertIndex++;
  3531.  
  3532.     Dir->fsd_DirCount++;
  3533.  
  3534.     // einfügen ab <InsertIndex>
  3535.     for (Index=Dir->fsd_DirCount; Index > InsertIndex; Index--)
  3536.         Dir->fsd_EntryList[Index] = Dir->fsd_EntryList[Index-1];
  3537.  
  3538.     Dir->fsd_EntryList[InsertIndex] = FSe;
  3539.  
  3540.     return InsertIndex;
  3541. }
  3542.  
  3543.  
  3544. static BOOL isInWindow(struct Window *Win, short x, short y)
  3545. {
  3546.     struct Layer *wLayer;
  3547.  
  3548.     wLayer = WhichLayer(&Win->WScreen->LayerInfo,
  3549.             x + Win->LeftEdge,
  3550.             y + Win->TopEdge);
  3551.  
  3552.     return (BOOL) (wLayer == Win->RPort->Layer);
  3553. }
  3554.  
  3555.  
  3556. static void GetPatternGadgetString(void)
  3557. {
  3558.     stccpy(SelectPattern.RawName, GADSTRING(FSGadgets[GDX_FSPatternGadget]), sizeof(SelectPattern.RawName));
  3559.  
  3560.     if(ParsePatternNoCase(SelectPattern.RawName,
  3561.             SelectPattern.ParsedPattern,
  3562.             sizeof(SelectPattern.ParsedPattern) ) == -1)
  3563.         {
  3564.         alarm("%s: %s", __FUNC__, GetString(MSG_XLATEERROR_SELECT));
  3565.         SelectPattern.isParsed = FALSE;
  3566.         }
  3567.     else
  3568.         {
  3569.         SelectPattern.isParsed = TRUE;
  3570.         }
  3571. }
  3572.  
  3573.  
  3574. // Der FontName muß im Format "nnnnnnnnn.font/99" oder "nnnnnnnnn.font 99" vorliegen!
  3575. BOOL FillTextAttrFromFontName(struct TextAttr *FontAttr, const char *FontName)
  3576. {
  3577.     const char *fp;
  3578.     char *p;
  3579.     size_t Len;
  3580.  
  3581.     // zuerst die Länge des Namens bestimmen
  3582.     for (fp = FontName, Len = 0; *fp && '/' != *fp && ' ' != *fp; fp++, Len++);
  3583.  
  3584.     FontAttr->ta_Name = malloc(Len + 1);
  3585.     if (NULL == FontAttr->ta_Name)
  3586.         return FALSE;
  3587.  
  3588.     p = FontAttr->ta_Name;
  3589.     while (*FontName && '/' != *FontName && ' ' != *FontName)
  3590.         {
  3591.         *p++ = *FontName++;
  3592.         }
  3593.     *p = '\0';    // ta_Name mit '\0' abschließen
  3594.  
  3595.     // Trenner zwischen Name und Größe überspringen
  3596.     if (*FontName)
  3597.         FontName++;
  3598.  
  3599.     FontAttr->ta_YSize = atoi(FontName);
  3600.     FontAttr->ta_Style = FS_NORMAL;
  3601.     FontAttr->ta_Flags = 0;
  3602.  
  3603.     return TRUE;
  3604. }
  3605.  
  3606.  
  3607. void SetFSListFont(struct BackupOptions *Opt)
  3608. {
  3609.     static struct TextAttr myTextAttr;
  3610.  
  3611.     FillTextAttrFromFontName(&myTextAttr, Opt->bo_ListFontName);
  3612.  
  3613.     FileDisplayScr.sFont = OpenDiskFont(&myTextAttr);
  3614.     if (NULL == FileDisplayScr.sFont)
  3615.         {
  3616.         alarm(GetString(MSG_CANNOTOPEN_LISTFONT),
  3617.             myTextAttr.ta_Name, myTextAttr.ta_YSize,
  3618.             DefaultFAttr.ta_Name, DefaultFAttr.ta_YSize
  3619.             );
  3620.         FileDisplayScr.sFont = OpenDiskFont(&DefaultFAttr);
  3621.         }
  3622.     if (myTextAttr.ta_Name)
  3623.         {
  3624.         free(myTextAttr.ta_Name);
  3625.         myTextAttr.ta_Name = NULL;
  3626.         }
  3627. }
  3628.  
  3629.  
  3630. void EndXGO(void)
  3631. {
  3632.     if (FSwin && FSGadgets[GDX_FSGlobOptGadget])
  3633.         {
  3634.         GT_SetGadgetAttrs(FSGadgets[GDX_FSGlobOptGadget], FSwin, NULL,
  3635.             GA_Disabled, FALSE,
  3636.             TAG_END);
  3637.         }
  3638. }
  3639.  
  3640.  
  3641. static ULONG __interrupt __saveds DisplayFileSizeHookFunc(struct Hook *HookPtr,
  3642.         struct FSDirEntry *Record, struct ALVDrawMsg *Msg )
  3643. {
  3644.     ULONG Result = 0l;
  3645.  
  3646.     if (ALV_GETUSERSTRING == Msg->alvdm_MethodID)
  3647.         {
  3648.         static char dBuff[40];
  3649.  
  3650.         switch (Record->fse_Typ)
  3651.             {
  3652.         case Volume:
  3653.             strcpy(dBuff, GetString(MSG_FILELIST_VOL));
  3654.             break;
  3655.         case Directory:
  3656.             strcpy(dBuff, GetString(MSG_FILELIST_DIR));
  3657.             break;
  3658.         case SoftLinkDir:
  3659.         case SoftLinkFile:
  3660.             strcpy(dBuff, GetString(MSG_FILELIST_SOFTLINK));
  3661.             break;
  3662.         case HardLinkFile:
  3663.         case HardLinkDir:
  3664.             strcpy(dBuff, GetString(MSG_FILELIST_HARDLINK));
  3665.             break;
  3666.         case Assign:
  3667.             strcpy(dBuff, GetString(MSG_FILELIST_ASSIGN));
  3668.             break;
  3669.         case File:
  3670.             myFormatString(dBuff, "%lU", Record->fse_Size);
  3671.             break;
  3672.         case Device:
  3673.             KMBytes(dBuff, Record->fse_Size);
  3674.             strcat(dBuff, GetString(MSG_FILELIST_PARTITION));
  3675.             break;
  3676.             }
  3677.  
  3678.         Result = (ULONG) dBuff;
  3679.         }
  3680.  
  3681.     return Result;
  3682. }
  3683.  
  3684.  
  3685. static ULONG __interrupt __saveds DisplayFileProtectionHookFunc(struct Hook *HookPtr,
  3686.         struct FSDirEntry *Record, struct ALVDrawMsg *Msg )
  3687. {
  3688.     ULONG Result = 0l;
  3689.  
  3690.     if (ALV_GETUSERSTRING == Msg->alvdm_MethodID)
  3691.         {
  3692.         switch (Record->fse_Typ)
  3693.             {
  3694.         case Volume:
  3695.         case Device:
  3696.         case Assign:
  3697.             Result = (ULONG) "";
  3698.             break;
  3699.         case Directory:
  3700.         case File:
  3701.         case HardLinkFile:
  3702.         case HardLinkDir:
  3703.         case SoftLinkDir:
  3704.         case SoftLinkFile:
  3705.             Result = (ULONG) GetFileFlags(Record->fse_Protection);
  3706.             break;
  3707.             }
  3708.         }
  3709.  
  3710.     return Result;
  3711. }
  3712.  
  3713.  
  3714. static ULONG __interrupt __saveds DisplaySelectHookFunc(struct Hook *HookPtr,
  3715.         struct FSDirEntry *Record, struct ALVDrawMsg *Msg )
  3716. {
  3717.     struct RastPort *rp;
  3718.     const short SelectMarkerWidth = 2 * 8;
  3719.  
  3720.     rp = Msg->alvdm_RastPort;
  3721.  
  3722.     switch (Msg->alvdm_MethodID)
  3723.         {
  3724.     case ALV_DRAW:
  3725.         if (!isFile(Record))
  3726.             {
  3727.             d(kprintf(__FUNC__ "/%ld: MinY=%ld MaxY=%ld\n", \
  3728.                 __LINE__, Msg->alvdm_Bounds.MinY, Msg->alvdm_Bounds.MaxY));
  3729.  
  3730.             DrawSelectMarker(rp, 
  3731.                 Msg->alvdm_Bounds.MinX, Msg->alvdm_Bounds.MinY,
  3732.                 SelectMarkerWidth, Record, Msg);
  3733.             }
  3734.         break;
  3735.  
  3736.     case ALV_GETBOUNDS:
  3737.         {
  3738.         Msg->alvdm_Bounds.MinX = 0;
  3739.         Msg->alvdm_Bounds.MinY = 0;
  3740.  
  3741.         if (isFile(Record))
  3742.             {
  3743.             Msg->alvdm_Bounds.MaxY = 0;
  3744.             Msg->alvdm_Bounds.MaxX = 0;
  3745.             }
  3746.         else
  3747.             {
  3748.             Msg->alvdm_Bounds.MaxY =
  3749.             Msg->alvdm_Bounds.MaxX = SelectMarkerWidth;
  3750.             }
  3751.         }
  3752.         break;
  3753.         }
  3754.  
  3755.     return 0l;
  3756. }
  3757.  
  3758.  
  3759. static ULONG __interrupt __saveds ClickFileHookFunc(struct Hook *HookPtr,
  3760.         struct FSDirEntry *Record, struct ALVDrawMsg *Msg )
  3761. {
  3762.     ULONG Result = ALVRET_REUSE;
  3763.  
  3764.     if (ALV_RECORDCLICKED == Msg->alvdm_MethodID)
  3765.         {
  3766.         if (Msg->alvdm_ColNo == 1 && !isFile(Record) )
  3767.             {
  3768.             struct FSSelectedRecord *NewFSS;
  3769.  
  3770.             NewFSS = malloc(sizeof(struct FSSelectedRecord));        
  3771.             if (NewFSS)
  3772.                 {
  3773.                 NewFSS->fsr_Record = Record;
  3774.                 AddTail((struct List *) &SubDirRecordsList, (struct Node *) &NewFSS->fsr_Node);
  3775.                 }
  3776.             Result = ALVRET_NOREUSE;
  3777.             }
  3778.         else
  3779.             Result = ALVRET_REUSE;
  3780.         }
  3781.  
  3782.     return Result;
  3783. }
  3784.  
  3785.  
  3786. static ULONG __interrupt __saveds SelectFileHookFunc(struct Hook *HookPtr,
  3787.         struct FSDirEntry *Record, struct ALVDrawMsg *Msg )
  3788. {
  3789.     ULONG Result = 0l;
  3790.  
  3791.     if (ALV_RECORDSELECTED == Msg->alvdm_MethodID)
  3792.         {
  3793.         struct FSSelectedRecord *NewFSS;
  3794.  
  3795.         NewFSS = malloc(sizeof(struct FSSelectedRecord));        
  3796.         if (NewFSS)
  3797.             {
  3798.             NewFSS->fsr_Record = Record;
  3799.             AddTail((struct List *) &SelectRecordsList, (struct Node *) &NewFSS->fsr_Node);
  3800.             }
  3801.         }
  3802.  
  3803.     return Result;
  3804. }
  3805.  
  3806.  
  3807. // Test, ob die Mauskoordinaten innerhalb des FSALVGadget liegen
  3808. static BOOL isInFileView(WORD MouseX, WORD MouseY)
  3809. {
  3810.     if (MouseX < FSGadgets[GDX_FSALVGadget]->LeftEdge ||
  3811.             MouseX >= FSGadgets[GDX_FSALVGadget]->LeftEdge + FSGadgets[GDX_FSALVGadget]->Width)
  3812.         return FALSE;
  3813.     if (MouseY < FSGadgets[GDX_FSALVGadget]->TopEdge ||
  3814.             MouseY >= FSGadgets[GDX_FSALVGadget]->TopEdge + FSGadgets[GDX_FSALVGadget]->Height)
  3815.         return FALSE;
  3816.  
  3817.     return TRUE;
  3818. }
  3819.  
  3820.  
  3821. void ShowWildcardOpt(const struct BackupOptions *Opts)
  3822. {
  3823.     if (FSwin)
  3824.         {
  3825.         GT_SetGadgetAttrs(FSGadgets[GDX_FSWildTypeGadget], FSwin, NULL,
  3826.             GTTX_Text, Opts->bo_UseGrepPattern ? "#?" : "*",
  3827.             TAG_END);
  3828.         }
  3829. }
  3830.  
  3831.  
  3832. static void __interrupt DrawMarkerBox(struct RastPort *rp, short xMin, short xMax, short yMin, short yMax)
  3833. {
  3834.     Point PointArray[8];
  3835.  
  3836.     PointArray[0].x = PointArray[3].x = xMax - 2;
  3837.     PointArray[1].x = PointArray[2].x = xMax;
  3838.     PointArray[4].x = PointArray[7].x = xMin + 2;
  3839.     PointArray[5].x = PointArray[6].x = xMin;
  3840.  
  3841.     PointArray[0].y = PointArray[7].y = yMin;
  3842.     PointArray[1].y = PointArray[6].y = yMin + 2;
  3843.     PointArray[2].y = PointArray[5].y = yMax - 2;
  3844.     PointArray[3].y = PointArray[4].y = yMax;
  3845.  
  3846.     Move(rp, PointArray[7].x, PointArray[7].y);
  3847.     PolyDraw(rp, 8, (WORD *) PointArray);
  3848. }
  3849.  
  3850.  
  3851. static void __interrupt DrawSelectMarker(struct RastPort *rp, short x, short y, short Width,
  3852.         const struct FSDirEntry *Record, const struct ALVDrawMsg *Msg)
  3853. {
  3854.     short Height;
  3855.     short xMax, yMax;
  3856.     short wDiff = 3, hDiff = 3;
  3857.  
  3858.     Height = Msg->alvdm_Bounds.MaxY - y;
  3859.  
  3860.     xMax = x + Width - 1;
  3861.     yMax = y + Height - 1;
  3862.  
  3863.     if ((Height - 1 - 2 * hDiff) < 3)
  3864.         hDiff--;
  3865.  
  3866. //    DrawMarkerBox(rp, x, xMax, y, yMax);
  3867.  
  3868.     // leeres Rechteck zeichnen
  3869.     SetAPen(rp, Msg->alvdm_DrawInfo->dri_Pens[TEXTPEN]);
  3870.     Move(rp, x + wDiff, y + hDiff);
  3871.     Draw(rp, xMax - wDiff, y + hDiff);
  3872.     Draw(rp, xMax - wDiff, yMax - hDiff);
  3873.     Draw(rp, x + wDiff, yMax - hDiff);
  3874.     Draw(rp, x + wDiff, y + hDiff);
  3875.  
  3876. //    Record->dli_dNode->SelectState = GetDirSelectState(Record->dli_dNode);
  3877.  
  3878.     if (Record->fse_HasSelects)
  3879.         {
  3880.         // einige Files sind ausgewählt
  3881.         short k;
  3882.  
  3883.         for (k=x+wDiff; k<xMax-wDiff; k++)
  3884.             {
  3885.             Move(rp, k, yMax - hDiff);
  3886.             Draw(rp, xMax - wDiff, y + hDiff);
  3887.             }
  3888.         }
  3889.     else if (ST_Selected == Record->fse_Selected)
  3890.         {
  3891.         // alle Files sind ausgewählt
  3892.         RectFill(rp, x + wDiff, y + hDiff, xMax - wDiff, yMax - hDiff);
  3893.         }
  3894. }
  3895.  
  3896.  
  3897.